Resolving file paths within MSI databases can be a complex piece of coding. It involves linking files to components and components to the directory table. The complexity is due to the flexibility of Windows Installer in determining how directory table entries are referenced.
The directory table of Windows Installer databases uses chained entries to construct a resultant target path for directories. These directory chains can be altered by custom actions and DOS environment variables.
The script below is an example of how to resolve files from within an MSI to the actual paths from which the file can be expected to be installed.
Using the Script
The header of the script allows for specifying the path to an MSI, the path to the text based report that is to be generated and (if required) a Transform that can be used with the specified MSI. The script resolves files within an MSI to a true path and can be modified to also list file versions, file sizes or file hashes. These properties need to be set before the example can be used.
The script is part of an "MSI Check" utility that I wrote many years ago for creating Infopath based QA documents for Windows Installer packages. Feel free to download the entire set of scripts from the link mentioned.
[[vb]] '**************************************** 'Declare variables '**************************************** Const HKEY_CURRENT_USER = &H80000001 const HKEY_LOCAL_MACHINE = &H80000002 '**************************************** ' Set Reporing Properties '**************************************** 'Set the name and path of the MSI file that is to be queried strMsiFile = "H:\vc_red.msi" 'If a transform is being used, specify that location strTransformFile = "" 'Set the output report location strReportlocation = "H:\MSIReport.xml" '**************************************** ' Set Objects '**************************************** Set objShell = CreateObject("WScript.Shell") set objFSO = CreateObject("scripting.FileSystemObject") Set Installer = CreateObject("WindowsInstaller.installer") set outfile = objFSO.OpenTextFile(strReportlocation, 8,True,-1) 'open for append Set Database = Installer.OpenDatabase(strMsiFile, 0) If Not strTransformFile ="" Then Database.ApplyTransform strTransformFile, 0 End if '**************************************** 'Script '**************************************** 'we have to be sure that there is a File table within the MSI. if DoesTableExist("File") = False then message = message &"This database does not contain any files" &chr(13) &chr(10) ScriptResult = "Pass" cleanup Wscript.quit end if 'Methodology 'Correctly interpreting Directory structures is complex due to teh flexibility of Windows Installer 'Major complexities occur with: ' * Custom Actions being used to set directories via properties ' * Properties being used to specify directory names and locations ' * MS visual Studio packages that do not have INSTALLDIR references ' * CSDIL directory references ' * NO-OPS dirs that dont actually a directory name 'This is a long and confusing script - for ease of understanding it's broken into staged categories 'that occur sequentially: ' 1. Custom Actions - determine properties set by Custom Actions & verifying they are part of the InstallExecute Sequence ' 2. Directory Table - establishing a table in memory to link directories with actual names ' 3. CSIDL Dir & Longname Resolution - Resolving CSIDL directories and proper 32bit long names ' 4. Apply Custom Actions Changes - Resolving all changes made by Custom Actions to the Directory Table ' 5. Apply Custom Actions Changes #2 - mostly redundant code... more testing is required ' 6. Apply the Property table Changes ' 7. Link Directories - Create the full directory chains ' 8. Directories set as other Directory References - a really nasty thing to do but it's found. ' 9. Resolve DOS ENV directory References (DOS Environment variables used within Directories ' 10. Clean NO Ops Dir References ' 11. Property Hardcoding Resolution - probably redundant code... left for an opportunity to refine and test 'The difficulty of determining the Directory table is complete - the remaining tasks link files to directories ' 12. Link Files & Components via a Dictionary ' 13. Create a file array for resolving all files to respective directory paths ' 14. Bubble Sort resultant File Paths '************************* 'Custom Actions '************************* 'Lets find out how many custom actions are involved in setting directories Type5lcount=0 if DoesTableExist("CustomAction") = True then 'We know there are custom actions but are there custom actions of type 51? ' Recursively list the entries within the Custom Actions Table Set View = DataBase.OpenView("SELECT * FROM CustomAction") View.execute Set record = view.Fetch While Not (record Is Nothing) if Record.StringData(2)=51 or Record.StringData(2)=307 then Type5lcount=Type5lcount+1 end if Set record = view.Fetch Wend end if 'If Type 51 Custom Actions exist we'll need to create an array of their values if Type5lcount > 0 then redim Type5lArray(Type5lcount,3) ' Recursively list the entries within the Custom Actions Table 'And populate the created array Type5lcount=0 Set View = DataBase.OpenView("SELECT * FROM CustomAction") View.execute Set record = view.Fetch While Not (record Is Nothing) if Record.StringData(2)=51 or Record.StringData(2)=307 then Type5lArray(Type5lcount,1) = Record.StringData(3) 'Source Type5lArray(Type5lcount,2) = Record.StringData(4) 'Target Type5lcount=Type5lcount+1 end if Set record = view.Fetch wend end if 'within out type51 array we have to recursively look for each property 'as MSI's are installed silently we dont want to include logic that does not occur under 'the InstallExecutesequence if isarray(Type5lArray) then for x = 0 to ubound(Type5lArray) 'msgbox "current = " &x &"action =" &Type5lArray(x,1) Set view = DataBase.OpenView("SELECT * FROM InstallExecuteSequence WHERE Action ='" &Type5lArray(x,1) &"'") View.execute Set record = view.Fetch if Not (record Is Nothing) then Type5lArray(x,3) = 1 end if next end if 'Directory Table Set View = DataBase.OpenView("SELECT * FROM Directory") View.execute Set record = view.Fetch ' Recursively list the entries within the Table DirectoryCount-0 While Not (record Is Nothing) DirectoryCount=DirectoryCount+1 Set record = view.Fetch wend DirectoryCount=DirectoryCount-1 'we know the number of entries within the array ' we have to declare our array now redim DirArray(DirectoryCount,7) 'We can now populate the array DirectoryCount=0 Set record = view.Fetch While Not (record Is Nothing) DirArray(DirectoryCount,1)= Record.StringData(1) 'DirectoryName DirArray(DirectoryCount,2)= Record.StringData(2) 'Directory parent 'Make an adjustment for TargetDir If not Record.StringData(1) = "TARGETDIR" then DirArray(DirectoryCount,3)= longname(Record.StringData(3)) 'DefaultDir DirArray(DirectoryCount,5)= Record.StringData(2) 'Next Parent DirArray(DirectoryCount,6)= longname(Record.StringData(3)) 'Readablename 'Only targetdir is resolved DirArray(DirectoryCount,7)= longname(Record.StringData(3)) 'DefaultDirname - not to be altered end if If Record.StringData(2) = "" then DirArray(DirectoryCount,4)= "1" 'IsResolved 'targetDir is itself resolved end if DirectoryCount=DirectoryCount+1 Set record = view.Fetch wend DirectoryCount=DirectoryCount-1 'troubleshoot 'CSIDL Dir & Longname Resolution 'SourceDir targetdir - DefaultDir name resolution 'Anything that contains a colon in the Default Dir column states that the source of the files for that 'directory come from a different folder structure. The Source is not what we are interested in 'so to resolve directory names correctly, we remove anything that comes after (and including) the colon for x = 1 to ubound(dirarray) if instr(DirArray(x,3),":") >0 then DirArray(x,3) = left(DirArray(x,3),instr(DirArray(x,3),":") -1) end if next For x = 0 to DirectoryCount If DirArray(x,1)="TARGETDIR" then 'Packages without INSTALLDIR are resolved via TARGETDIR if CATargetDir = Nul then DirArray(x,6) = "C:\" DirArray(x,3) = "C:\" DirArray(x,4) = "1" 'IsResolved else DirArray(x,6) = CATargetDir DirArray(x,3) = CATargetDir DirArray(x,4) = "1" 'IsResolved end if end if If DirArray(x,2)="TARGETDIR" then 'test to see if a CSIDL directory exists 'because of Merge modules we have to parse & split directory names at a period TempDir="" if instr(DirArray(x,1),".") >0 then tempdirarray=split(DirArray(x,1),".") TempDir =tempdirarray(0) else TempDir = DirArray(x,1) end if 'The Tempdir variable will be set for checking resolution 'The parsed directory name must now be checked against the CSIDL list 'If CSIDL is not detected the original string is returned. if not ResolveDirName( "[" &TempDir &"]") = "[" &TempDir &"]" then DirArray(x,6) = ResolveDirName( "[" &TempDir &"]") DirArray(x,3) = ResolveDirName( "[" &TempDir &"]") DirArray(x,4) = 1 'Directory is resolved end if end if next 'Apply Custom Actions Changes For x = 0 to DirectoryCount 'we insert Logic for directories being hard set through Custom Actions 'This is done after other logic as the values for these directories are being 'Hard Set, regardless of MSI Rules if Type5lCount > 0 then for y = 0 to Type51Count if DirArray(x,1) = Type5lArray(y,l) AND Type5lArray(y,3) = 1 then 'we have a directory being Hardcoded through Type 51 Custom Actions DirArray(x,2)= "" 'No directory parent if resolved by Custom Action DirArray(x,4)= "1" 'IsResolved varTemp=Type5lArray(y,2) DirArray(x,3)= ResolveDirName(varTemp) DirArray(x,6)= ResolveDirName(varTemp) y = Type5lCount end if next end if next 'Custom Action properties can also be used as part of destination strings for directories 'Any Type 51 properties need to be set For x = 0 to DirectoryCount if Type5lCount > 0 then for y = 0 to Type5lCount DirArray(x,6) = Replace (DirArray(x,6),"[" & Type5lArray(y,l) &"]" , Type5lArray(y,2)) DirArray(x,3) = Replace (DirArray(x,3),"[" & Type5lArray(y,l) &"]" , Type5lArray(y,2)) next end if next 'Apply Custom Actions Changes #2 'just when you thought there couldn't possibly be any more to deal with 'We find more potental uses for Type 51 Custom Actions for x= 0 to ubound(dirarray) if instr(DirArray(x,6),"[") > 0 then 'we need to check the Type 51 Custom Actions for y = 0 to Ubound(Type5lArray) 'would you believe we have to do this twice due to one really crappy pckage! if instr(DirArray(x,6),"[" &Type5lArray(y,l) &"]") > 0 AND Type5lArray(y,3) = 1 then' this directory references a second directory\ DirArray(x,6) = Replace(DirArray(x,6),"[" &Type5lArray(y,l) &"]",Type5lArray(y,2) &"\",1,-1,VbTextCompare) DirArray(x,3) = Replace(DirArray(x,3),"[" &Type5lArray(y,l) &"]",Type5lArray(y,2) &"\",1,-1,VbTextCompare) end if if instr(DirArray(x,6),"[" &Type5lArray(y,l) &"]") > 0 AND Type5lArray(y,3) = 1 then' this directory references a second directory\ DirArray(x,6) = Replace(DirArray(x,6),"[" &Type5lArray(y,l) &"]",Type5lArray(y,2) &"\",l,-l,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[" &Type5lArray(y,l) &"]",Type5lArray(y,2) &"\",l,-l,VbTextCompare) end if Next end if next 'oh the never ending variance of ways to set a directory 'This is very unusual for x= 0 to ubound(dirarray) tempstring="" for y = 1 to 5 if tempstring ="" then tempstring =DirArray(x,6) else end if if instr(tempstring,"[") > 0 and instr(tempstring,"]") > 0 then tempstring=right(tempstring,len(tempstring) - instr(tempstring,"[") + 1) tempstringright=tempstring 'we'll save this for later tempstring=left(tempstring,instr(tempstring,"]")) 'the tempstring is now a property - we need to compare that property to the directory table 'and to the Property table if instr(ResolveDirName(tempstring),"c:\") > 0 then DirArray(x,4) = 1 'Directory is resolved DirArray(x,6) = Replace (DirArray(x,6),tempstring,ResolveDirName(tempstring) &"\",1,-1,vbTextcompare) end if 'the ResolveDirname always references C:\ tempstring = right(tempstringright,len(tempstringright)-len(tempstring)) else Y=5 end if next next 'Apply Property Table Changes 'We must also account for directories that are having their Paths directly set through the Property table 'we will run an sql query against the entries of the property table to see if they contain driver references 'if so, stamp their value against the directory table 'we have to be sure that there is a File table within the MSI. Set View = DataBase.OpenView("SELECT * FROM Property") View.execute Set record = view.Fetch While Not (record Is Nothing) If instr(Record.StringData(2), ":\") > 0 then 'This particular property is being hardcoded - we need For x = 0 to ubound(DirArray) if Record.StringData(1) = DirArray(x,1) then 'the property is setting this directory location DirArray(x,6) = Record.StringData(2) DirArray(x,3) = Record.StringData(2) DirArray(x,4) = 1 'Directory is resolved x = ubound(DirArray) end if next end if Set record = view.Fetch wend 'of course the Property table can be used to just set directory names - we should take them into account Set view = DataBase.OpenView("SELECT * FROM Property") view.execute set record = view.Fetch while Not (record Is Nothing) 'This particular property is being hardcoded - we need to check against our directory table For x = 0 to ubound(DirArray) if instr(DirArray(x,6), "[" &Record.stringData(1) &"]" ) > 0 then DirArray(x,6) = Replace (DirArray(x,6),"[" &Record.StringData(1) &"]",Record.stringData(2),1,-1,vbTextcompare) end if next set record = view.Fetch wend '************************* 'Link Directories '************************* 'Our DirArray contains the names of every entry from the directory table 'we need to recursively reference these tables until we can resolve a full path 'A directory chain is fully resolved once the Directory Parent to a Directory chain is'set to TARGETDIR 'Code rework will be needed later to resolve this. 'troubleshoot For x = 0 to ubound(DirArray) ' msgbox x &" of " &ubound(DirArray)' ' msgbox Ucase(DirArray(x,5)) ' troubleshoot 'do this for each directory entry in our array isresolved=0 noparent=0 do until isresolved = 1 or noparent=1 'make sure that every directory is resolved 'as a sanity check - if a drive reference exists dont ty to resolve any further if instr(DirArray(x,6),":\") > 1 then isresolved = 1 Exit DO end if 'The fourth field in the table is set to 1 when the directory is resolved if DirArray(x,4)= "1" then isresolved = 1 Exit DO else 'the directory is not resolved... we need to find the next parent within the array For z = 0 to ubound(DirArray) 'Find the next parent of the problem directory 'troubleshoot 'msgbox DirArray(z,1) if Ucase(DirArray(x,5)) = Ucase(DirArray(z,1)) then 'we have found the Next Parent DirArray(x,5) = DirArray(z,5) If DirArray(z,4) = "1" then 'the parent is resolved so we add it to the readable directory chain DirArray(x,6)= DirArray(z,6) &"\" &DirArray(x,6) 'and indicate that our directory is now resolved as well. DirArray(x,4) = "1" isresolved =1 exit do else 'add the parent directory to the chain & set the new parent to be that former grandparent DirArray(x,6)= DirArray(z,3) &"\" &DirArray(x,6) DirArray(x,5) = DirArray(z,5) z = ubound(dirarray) end if end if next end if loop next 'Directories set as other Directory References 'There are situations where Custom Actions set a directory path to be that of another 'property in the Directory table... this shouldn't be done but a number 'of Microsoft packages do this. 'We do one more sweep of the table to see if Resolved directories are referencing another 'Directory property For z = 0 to ubound(dirarray) if instr(DirArray(z,6),"[")= 1 then 'we have an unresolved directory referencing a Property for y = 0 to ubound(dirarray) if instr(DirArray(z,6),"[" &DirArray(y,1) &"]") =1 then' this directory references a second directory DirArray(z,6) = Replace(DirArray(z,6),"[" &DirArray(y,1) &"]",DirArray(y,6) &"\",1,-1,VbTextCompare) y = DirectoryCount end if next end if next '************************* 'Resolve DOS ENV directory References '************************* for x = 0 to ubound(DirArray) 'msgbox DirArray(x,6) DirArray(x,6) = Replace(DirArray(x,6),"[%AllUsersProfile]","C:\Documents and Settings\All Users",1,-1,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[%AppData]","C:\Documents and Settings\Username\Application Data",1,-1,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[%CommonProgramFiles]","C:\Program Files\Common Files",1,-1,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[%ProgramFiles]","C:\Program Files",1,-1,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[%SystemDrive]","C:\",1,-1,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[%SystemRoot]","C:\Windows",1,-1,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[%Temp]","C:\Documents and Settings\username\Local Settings\Temp",1,-1,VbTextCompare) DirArray(x,6) = Replace(DirArray(x,6),"[%UserProfile]","C:\Documents and Settings\Username",1,-1,VbTextCompare) next 'Add trailing backslashes to directory references as per MSI standards For x = 0 to ubound(dirarray) if not instrrev(DirArray(x,6),"\") = len(DirArray(x,6)) then 'add a backslash DirArray(x,6) = DirArray(x,6) &"\" end if next '************************* 'Clean NO Ops Dir References '************************* For x = 0 to ubound(dirarray) 'The only other thing needed to be purged are double backslashes & no op dirs do until instr(DirArray(x,6),"\.")=0 DirArray(x,6) = Replace(DirArray(x,6),"\.","\") Loop do until instr(DirArray(x,6),".\")=0 DirArray(x,6) = Replace(DirArray(x,6),".\","\") Loop do until instr(DirArray(x,6),"\\")=0 DirArray(x,6) = Replace(DirArray(x,6),"\\","\") Loop if instr(DirArray(x,6),"\") = 1 then DirArray(x,6)= right(DirArray(x,6),len(DirArray(x,6))-1) end if Next '************************* 'Property Hardcoding Resolution '************************* 'We have to again look at the property table for hardcoded values 'let's create a dictionary to hold property values Set View = DataBase.OpenView("SELECT * FROM Property") View.execute Set record = view.Fetch while Not (record Is Nothing) For x = 0 to ubound(dirarray) 'look at each directory we have if instr(DirArray(x,6),"[" &Record.StringData(1) &"]") = 1 then 'we have a property that's been hard set. 'Finally check properties against all of our directory entries DirArray(x,6) = Replace(DirArray(x,6),"[" &Record.StringData(1) &"]",Record.StringData(2),1,-1,VbTextCompare) end if next Set record = view.Fetch Wend For x = 0 to ubound(dirarray) 'all directories should now be resolved to a drive or a property in the case of Appsearch if instr(DirArray(x,6),":\") = 2 OR instr(DirArray(x,6),"[") = 1 then 'the directory is resolved else 'we assume the Rootdrive will be C:\ DirArray(x,6) = "C:\" &DirArray(x,6) end if next 'Directory Resolution is complete... now we link files to Directories via the Component tabl references '*********************** 'Link Files & Components via a Dictionary '*********************** 'The first step is to take all the directory paths and link them to components 'The components can then link file names to give an absolute reference 'We will then have an array listing the fullfilename of every directory and 'file within the package 'We'll create an array of the file table where we can list the InternalMSlFilename with the 'Component and absoute path of the component 'Create a dictionary of File resolution Set Directorylist = CreateObject("Scripting.Dictionary") For x = 0 to DirectoryCount Directorylist.Add DirArray(x,1) , DirArray(x,6) Next Dim FileComponent Set FileComponent = CreateObject("Scripting.Dictionary") Set View = DataBase.OpenView("SELECT * FROM Component") View.execute Set record = view.Fetch While Not (record Is Nothing) 'Add to the dictionary the list of components - Directory locations FileComponent.Add Record.StringData(1), Record.StringData(3) 'Component Set record = view.Fetch Wend '*********************** 'Create a file array for resolving all files to respective directory paths '*********************** 'Set a counter for the numberof files Filecount=0 Set View = DataBase.OpenView("SELECT * FROM File") View.execute Set record = view.Fetch while Not (record Is Nothing) Filecount=Filecount+1 Set record = view.Fetch Wend redim FileArray(Filecount-1,3) ' Recursively list the entries within the Custom Actions Table 'And populate the created array Filecount=0 Set View = DataBase.OpenView("SELECT * FROM File") View.execute Set record = view.Fetch while Not (record Is Nothing) FileArray(Filecount,1)= Record.StringData(1) 'Internal MSI Filename FileArray(Filecount,2)= Directorylist.Item(FileComponent.Item(Record.StringData(2))) & longname(Record.StringData(3)) 'taking component name & translating it to a directory reference FileArray(Filecount,3)= longname(Record.StringData(3)) 'filename Filecount=Filecount+1 Set record = view.Fetch wend 'Bubble Sort resultant File Paths 'Up to this point, every check has been to determine where files get installed to 'Now we check to see if any of the files are a problem 'lets attempt to modify Bubble sort to order the array 'Bubble Sort... Thanks to Richard Lowe for the code for i = uBound(FileArray) - 1 TO 0 Step -1 for j= 0 to i if FileArray(j,2)>FileArray(j+1,2) then temp= FileArray(j+1,2) temp2= FileArray(j+1,1) temp3= FileArray(j+1,2) FileArray(j+1,2)=FileArray(j,2) FileArray(j+1,1)=FileArray(j,1) FileArray(j+1,3)=FileArray(j,3) FileArray(j,2)=temp FileArray(j,1)=temp2 FileArray(j,3)=temp3 end if next next 'validation Check for x = 0 to ubound(FileArray) message=message &FileArray(x,2) &chr(13) &chr(10) next ScriptResult = "Info" '**************************************** 'Cleanup '**************************************** Results Cleanup '**************************************** 'Functions and Subs '**************************************** sub Results outfile.writeline( "") outfile.writeline( "" &Message &"") outfile.writeline( "") outfile.writeline( "") outfile.close end sub function DoesTableExist(strTableName) Set View = DataBase.Openview("SELECT * FROM _Tables") view.execute Set record = view.Fetch tablefound=0 While Not (record Is Nothing) and tablefound=0 if Record.Stringdata(1) = strTableName then tablefound=1 end if Set record = view.Fetch wend if tablefound=0 then DoesTableExist=False else DoesTableExist=True end if end function function MakeSafe(tempstring) tempstring = Replace (tempstring,">",">") tempstring = Replace (tempstring,"","") tempstring = Replace (tempstring,"&","&") tempstring = Replace (tempstring,"'","'") tempstring = Replace (tempstring,chr(34),""") MakeSafe = tempstring end function sub Cleanup 'Set Objects to Nothing Set objShell = Nothing Set wshNetwork = Nothing Set Installer = Nothing Set View = Nothing set Record = Nothing End Sub '******************************** 'Routine for returning a 32bit filename function longname(Tempvar) Tempprefix=0 if instr(Tempvar,".:") =1 then Tempvar = right(Tempvar,len(Tempvar)-2) end if if instr(Tempvar,":") >0 then Tempvar = left(Tempvar,instr(Tempvar,":") -1) end if 'Take care of null ops dirs if Tempvar ="." then longname = "" end if If instr(Tempvar,"|") then 'The string contains long and short names Tempvar=right(tempvar, len(tempvar) - instr(tempvar,"|")) If Tempprefix=1 then Tempvar = ".:" &Tempvar end if end if longname = Tempvar End function ' ************* Routine for resolving CSIDL directory locations Function ResolveDirName(TempDirVar) dim ResolvedDirLocation varOriginalReference = TempDirVar if not instr(TempDirVar,"[") = 1 then TempDirVar ="[" &TempDirVar &"]" end if ResolvedDirLocation="" If TempDirVar = "[AppDataFolder]" then ResolvedDirLocation = "C:\Documents and Settings\Username\Application Data" end if If TempDirVar = "[AllUsersFolder]" then ResolvedDirLocation = "C:\Documents and Settings\All Users" end if If TempDirVar = "[AllUsersProfile]" then ResolvedDirLocation = "C:\Documents and Settings\All Users" end if If TempDirvar = "[AllUsersProfileFolder]" then ResolvedDirLocation = "C:\Documents and Settings\All Users" end if If TempDirvar = "[AdminTools]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Start Menu\Programs\Administrative Tools" end if If TempDirvar = "[AdminToolsFolder]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Start Menu\Programs\Administrative Tools" end if If TempDirvar = "[Common64]" then ResolvedDirLocation = "C:\Program Files\Common Files" end if If TempDirvar = "[Common64folder]" then ResolvedDirLocation = "C:\Program Files\Common Files" end if If TempDirvar = "[CommonAppData]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Application Data" end if If TempDirvar = "[CommonAppDataFolder]" then ResolvedDirLocation = "C:\Program Files\common Files" end if If TempDirvar = "[Common]" then ResolvedDirLocation = "C:\Program Files\Common Files" end if If TempDirvar = "[CommonFilesFolder]" then ResolvedDirLocation = "C:\Program Files\Common Files" end if If TempDirvar = "[CommonFiles64Folder]" then ResolvedDirLocation = "C:\Program Files\common Files" end if If TempDirvar = "[Desktop]" then ResolvedDirLocation = "C:\Documents and settings\Username\Desktop" end if If TempDirvar = "[DesktopFolder] " then ResolvedDirLocation = "C:\Documents and settings\Username\Desktop" end if If TempDirvar = "[Favorites]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Favorites" end if If TempDirvar = "[FavoritesFolder]" then ResolvedDirLocation = "C:\Documents and Settings\All User\Favorites" end if If TempDirVar = "[Fonts]" then ResolvedDirLocation = "C:\WINDOWS\Fonts" end if If TempDirVar = "[FontsFolder]" then ResolvedDirLocation = "C:\WINDOWS\ Fonts" end if If TempDirvar = "[GlobalAssemblyCache]" then ResolvedDirLocation = "C:\WINDOWS\Assembly" end if If TempDirvar = "[GAC]" then ResolvedDirLocation = "C:\WINDOWS\Assembly" end if If TempDirvar = "[LocalAppData]" then ResolvedDirLocation = "C:\Documents and Settings\Username\Application Data" end if If TempDirvar = "[LocalAppDataFolder]" then ResolvedDirLocation = "C:\Documents and Settings\Username\Local Settings\Application Data" end if If TempDirvar = "[Personal Folder]" then ResolvedDirLocation = "C:\Documents and settings\Username\My Documents" end if If TempDirVar = "[MyPictures]" then ResolvedDirLocation = "C:\Documents and Setti ngs\Username\My Documents\My Pictures" end if If TempDirvar = "[MyPicturesFolder] " then ResolvedDirLocation = "C:\Documents and Settings\Username\My Documents\My Pictures" end if If TempDirvar = "[Program Files]" then ResolvedDirLocation = "C:\Program Files" end if If TempDirvar = "[ProgramFilesFolder]" then ResolvedDirLocation = "C:\Program Files" end if If TempDirvar = "[Personal]" then ResolvedDirLocation = "C:\Documents and Setti ngs\username\My Documents" end if If TempDirvar = "[Personal folder]" then ResolvedDirLocation = "C:\Documents and settings\username\My Documents" end if If TempDirVar = "[PrimaryVolumePath]" then ResolvedDirLocation = "C:" end if If TempDirvar = "[ProgramFiles64]" then ResolvedDirLocation = "C:\Program Files" end if If TempDirvar = "[ProgramFiles64Folder]" then ResolvedDirLocation = "C:\Program Files" end if If TempDirvar = "[Programs]" then ResolvedDirLocation = "C:\Documents and Setti ngs\Al 1 Users\Start Menu\Programs" end if If TempDirvar = "[ProgramsFolder]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Start Menu\Programs" end if If TempDirVar = "[ProgramMenuFolder]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Start Menu\Programs" end if If TempDirvar = "[Recent]" then ResolvedDirLocation = "C:\Documents and settings\Username\Recent" end if If TempDirvar = "[RecentFolder]" then ResolvedDirLocation = "C:\Documents and Settings\Username\Recent" end if If TempDirvar = "[Start Menu]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Start Menu" end if If TempDirvar = "[StartMenuFolder]" then ResolvedDirLocation = "C:\Documents and Settings\All Users\Start Menu" end if If TempDirvar = "[SendTo]" then ResolvedDirLocation = "C:\Documents and settings\username\SendTo" end if If TempDirVar = "[SendToFolder]" then ResolvedDirLocation = "C:\Documents and settings\username\SendTo" end if If TempDirVar = "[ShellNew]" then ResolvedDirLocation = "C:\Windows\ShellNew" end if If TempDirVar = "[ShellNewFolder]" then ResolvedDirLocation = "C:\Windows\ShellNew" end if If TempDirVar = "[Startup]" then ResolvedDirLocation = "C:\Documents and settings\All users\Start menu\Programs\Startup" end if If TempDirvar = "[StartUpfolder]" then ResolvedDirLocation = "C:\Documents and Settings\A11 Users\Start Menu\Programs\Startup" end if If TempDirVar = "[systeml6folder]" then ResolvedDirLocation ="C:\Windows\System" end if If TempDirVar = "[System32]" then ResolvedDirLocation = "C:\Windows\System32" end if If TempDirVar = "[System32Folder]" then ResolvedDirLocation = "C:\Windows\System32" end if If TempDirvar = "[System64]" then ResolvedDirLocation = "C:\Windows\System64" end if If TempDirVar = "[system64folder]" then ResolvedDirLocation = "C:\Windows\System64" end if If TempDirVar = "[System]" then ResolvedDirLocation = "C:\windows\System" end if If TempDirVar = "[SystemFolder]" then ResolvedDirLocation = "C:\Windows\System32" end if If TempDirvar = "[SYSTemp]" then ResolvedDirLocation = "C:\Documents and settings\username\Local Settings\Temp" end if If TempDirVar = "[Temp]" then ResolvedDirLocation = "C:\Documents and Settings\username\Local Settings\Temp" end if If TempDirVar = "[TempFolder]" then ResolvedDirLocation = "C:\Documents and settings\username\Local Settings\Temp" end if If TempDirvar = "[TemplateFolder]" then ResolvedDirLocation = "C:\Windows\Templates" end if If TempDirvar = "[UserProfile]" then ResolvedDirLocation = "c:\Documents and Settings\username" end if If TempDirvar = "[UserProfileFolder]" then ResolvedDirLocation = "C:\Documents and Settings\Username" end if If TempDirVar = "[WinRoot]" then ResolvedDirLocation = "C:" end if If TempDirVar = "[Windowsvolume]" then ResolvedDirLocation = "C:" end if If TempDirVar = "[windows]" then ResolvedDirLocation = "C:\Windows" end if If TempDirvar = "[WindowsFolder]" then ResolvedDirLocation = "C:\Windows" end if If TempDirvar = "[WWWROOT]" then ResolvedDirLocation = "C:\Inetpub\wwwroot" end if If TempDirVar = "[NetHood]" then ResolvedDirLocation = "C:\Documents and settings\username\NetHood" end if If TempDirVar = "[NetHoodFolder]" then ResolvedDirLocation = "C:\Documents and Settings\username\NetHood" end if If TempDirVar = "[PrintHood]" then ResolvedDirLocation = "C:\Documents and Settings\username\PrintHood" end if If TempDirvar = "[PrintHoodFolder]" then ResolvedDirLocation = "C:\Documents and settings\username\PrintHood" end if if ResolvedDirLocation="" then ' msgbox "unresolved Dir=" &TempDirVar &chr(34) ResolveDirName =varOriginalReference else ResolveDirName = ResolvedDirLocation end if End Function 'Routine for retrieving TARGETDIR resolution from MS Packages Function CATargetDir() if DoesTableExist("CustomAction") = True then Set View = DataBase.OpenView("SELECT * FROM CustomAction WHERE Source = 'TARGETDIR'") View.execute Set record = view.Fetch tablefound=0 While Not (record Is Nothing) AND tablefound=0 if Record.StringData(2) = 307 then 'This is a Microsoft package setting TargetDir tablefound=1 CATargetDir = Record.StringData(4) end if Set record = view.Fetch Wend End if end Function sub troubleshoot() displaymessage="" for varx= 0 to ubound(DirArray) displaymessage = displaymessage & DirArray(varx,1) & "," & DirArray(varx,2) &"," &DirArray(varx,3) &"," &DirArray(varx,4) &"," &DirArray(varx,5) &"," &DirArray(varx,6) &chr(10) &chr(13) next wscript.echo displaymessage end sub function DoesTableExist(strTableName) Set View = DataBase.Openview("SELECT * FROM _Tables") view.execute Set record = view.Fetch tablefound=0 While Not (record Is Nothing) and tablefound=0 if Record.Stringdata(1) = strTableName then tablefound=1 end if Set record = view.Fetch wend if tablefound=0 then DoesTableExist=False else DoesTableExist=True end if end function [[/vb]]
- Log in to post comments