Script to Fix Square Bracket Handling Bug in WISE for Windows Installer
January 4, 2001
by John Loomes
This script addresses a bug in WISE for Windows Installer 3 where if a registry entry in an MSI package has a value that contains square brackets e.g. [value], then WISE
will interpret everything in between the brackets as an MSI property and attempt to resolve it via the Property table. This results in incorrect registry values begin written when the package is
installed. In order to make WISE interpret square brackets literally, it is necessary to use the following syntax:
[\[ ]<mystring>[\]].
This script walks through the
Regsitry table in an MSI package, and fixes values in square
brackets as it comes across them. It writes the changes it makes to
an Excel spreadsheet to enable you to check for errors.
N.B. This bug is fixed in the next
release of WISE for Windows Installer (apparently)...
' This utility analyses Wise
for windows installer packages, ' checks for Registry keys which
contain square brackets ([ ]) which ' are to be ignored in by the
installer and converts them to [\[ ] and [\]] ' This is done by
checking against the Property table
' Option
Explicit
Dim databasePath, szTableName, objFS Const
msiOpenDatabaseModeReadOnly = 0 Const msiOpenDatabaseModeTransact
= 1
set objFS = CreateObject( "Scripting.FileSystemObject"
)
Dim argNum, argCount:argCount =
Wscript.Arguments.Count If (argCount < 1)
Then databasePath = InputBox("Please enter the
Msi file name including
path",,"C:\testing\MYMSI.msi") if databasePath
= "" then Fail "Cancel
Selected" end if else
databasePath = Wscript.Arguments(0) End
If
' Enter the Table name to
update szTableName = InputBox("Please enter the Table name to
check",,"Registry") if szTableName = ""
then Fail "Cancel Selected" end
if
if (not objFS.FileExists(databasePath)) then Fail "File
does not exist"
' Dump Changes to an excel spreadsheet so it
can be analysed dim objXL, intIndex: intIndex = 2 set objXL =
CreateObject( "Excel.Application" ) objXL.Visible =
TRUE objXL.WorkBooks.Add objXL.Cells(1, 1).Value =
"Replacement String" objXL.Rows(1).Font.Bold = True
'
Export the Registry Table TableImpExp szTableName,
"Export"
' Process it to change source Const ForReading =
1, ForWriting = 2, ForAppending = 8 Dim InpFile, OutpFile,
objRegExp, szLine, szOutputLine, DeleteFile
Set objRegExp = new RegExp objRegExp.pattern =
"\[*\]" objRegExp.ignorecase =
TRUE Set InpFile =
objFS.OpenTextFile("C:\test.txt" , ForReading)
Set OutpFile = objFS.OpenTextFile("C:\test1.txt" , ForWriting,
True) While(InpFile.AtEndOfStream <>
True) szLine =
InpFile.readline if
(objRegExp.Test(szLine))
then
szOutputLine =
FixLine(szLine)
else
szOutputLine = szLine
end if
OutpFile.WriteLine(szOutputLine)
Wend InpFile.close
OutpFile.close
' Import the Registry Table TableImpExp
szTableName, "Import"
'Delete the temporary files
created Set DeleteFile =
objFS.GetFile("C:\test.txt") DeleteFile.Delete Set DeleteFile
= objFS.GetFile("C:\test1.txt") DeleteFile.Delete
wscript.Echo "Operation Complete" Wscript.Quit
0
'This function parses a line looking for [] combinations
and checks property and fixes Function FixLine(szLine) dim
iLSquareOff,iLSquareCurr,iRSquareOff,iRSquareCurr,szLReplace,
szRReplace dim szLLeave, szRLeave, szProperty,
szMatchFound iLSquareCurr=1:iRSquareCurr=1 szLReplace="[\[]":szRReplace="[\]]" szLLeave="[":szRLeave="]" FixLine
= "" do iLSquareOff =
instr(iLSquareCurr,szLine,"[") + 1 iRSquareOff
= instr(iRSquareCurr,szLine,"]") if
iRSquareOff=0 then
Fixline = FixLine &
mid(szLine,iRSquareCurr)
exit do end if Fixline =
FixLine & mid(szLine,iRSquareCurr,(ILSquareOff - IRSquareCurr
-1)) ' Need to put a fix in here for cases like
[\]] or [\[ ] etc szProperty =
mid(szLine,iLSquareOff,(IRSquareOff -
ILSquareOff)) szMatchFound =
msiPropertyExists(szProperty) if (szMatchFound
= "") then FixLine =
FixLine & szLReplace & szProperty &
szRReplace objXL.Cells(intIndex, 1).Value =
szLReplace & szProperty & szRReplace
intIndex = intIndex + 1
else FixLine = FixLine
& szLLeave & szProperty & szRLeave
end if iRSquareOff = iRSquareOff +
1 ILSquareCurr =
ILSquareOff IRSquareCurr =
IRSquareOff loop end function
' This function checks
the property table in the MSI database for szProperty Function
msiPropertyExists(szProperty) ' Process SQL statements Dim
query, view, record, message, szFirstChar
msiPropertyExists="TRUE" szFirstChar =
mid(szProperty,1,1) ' Check for special
characters in the first position if
szFirstChar = "!" then Exit Function if
szFirstChar = "$" then Exit Function if
szFirstChar = "~" then Exit Function if
szFirstChar = "#" then Exit Function if
szFirstChar = "\" then Exit Function if
szProperty = "SHELLNOOP" then Exit Function
msiPropertyExists="" ' Set to false after passing the tests
above ' Connect to Windows installer object Dim openMode :
openMode = msiOpenDatabaseModeTransact On Error Resume
Next Dim installer : Set installer = Nothing Set installer =
Wscript.CreateObject("WindowsInstaller.Installer") :
CheckError
' Open database Dim database : Set database =
installer.OpenDatabase(databasePath, openMode) :
CheckError
query = "Select Property FROM
Property WHERE Property='" & szProperty &
"'" Set view = database.OpenView(query) :
CheckError view.Execute :
CheckError Set record =
view.Fetch ' Big kludge here but should work.
When found record is defined otherwise use ""
msiPropertyExists=record.StringData(1)
If openMode = msiOpenDatabaseModeTransact
Then database.Commit
end function
sub
TableImpExp(szTable, ImpExp)
' Connect to Windows installer
object Dim openMode : openMode =
msiOpenDatabaseModeTransact On Error Resume Next Dim installer
: Set installer = Nothing Set installer =
Wscript.CreateObject("WindowsInstaller.Installer") :
CheckError
' Open database Dim database : Set database =
installer.OpenDatabase(databasePath, openMode) :
CheckError
if ImpExp = "Import" then ' Import the updated
table into the database database.import "C:\", "test1.txt" end
if if ImpExp = "Export" then ' Export the table to a
file database.export szTable , "C:\", "test.txt"
end
if
If openMode = msiOpenDatabaseModeTransact Then
database.Commit end Sub
Sub
CheckError Dim message,
errRec If Err = 0 Then Exit
Sub message = Err.Source & " " &
Hex(Err) & ": " & Err.Description If
Not installer Is Nothing
Then Set errRec =
installer.LastErrorRecord
If Not errRec Is Nothing Then message = message & vbLf &
errRec.FormatText End If
Fail message End Sub
Sub
Fail(message) Wscript.Echo
message Wscript.Quit 2 End
Sub
|