home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 June
/
Chip_2001-06_cd1.bin
/
zkuste
/
vbasic
/
Data
/
Utility
/
MSISDK15.msi
/
WiCompon.vbs
< prev
next >
Wrap
Text File
|
2000-10-05
|
9KB
|
182 lines
' Windows Installer utility to list component composition of an MSI database
' For use with Windows Scripting Host, CScript.exe or WScript.exe
' Copyright (c) 1999-2000, Microsoft Corporation
' Demonstrates the various tables having foreign keys to the Component table
'
Option Explicit
Public isGUI, installer, database, message, compParam 'global variables access across functions
Const msiOpenDatabaseModeReadOnly = 0
' Check if run from GUI script host, in order to modify display
If UCase(Mid(Wscript.FullName, Len(Wscript.Path) + 2, 1)) = "W" Then isGUI = True
' Show help if no arguments or if argument contains ?
Dim argCount:argCount = Wscript.Arguments.Count
If argCount > 0 Then If InStr(1, Wscript.Arguments(0), "?", vbTextCompare) > 0 Then argCount = 0
If argCount = 0 Then
Wscript.Echo "Windows Installer utility to list component composition in an install database." &_
vbLf & " The 1st argument is the path to an install database, relative or complete path" &_
vbLf & " The 2nd argument is the name of the component (primary key of Component table)" &_
vbLf & " If the 2nd argument is not present, the names of all components will be listed" &_
vbLf & " If the 2nd argument is a ""*"", the composition of all components will be listed" &_
vbLf & " Large databases or components are better displayed using CScript than WScript." &_
vbNewLine &_
vbNewLine & "Copyright (C) Microsoft Corporation, 1999-2000. All rights reserved."
Wscript.Quit 1
End If
' Connect to Windows Installer object
REM On Error Resume Next
Set installer = Nothing
Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError
' Open database
Dim databasePath:databasePath = Wscript.Arguments(0)
Set database = installer.OpenDatabase(databasePath, msiOpenDatabaseModeReadOnly) : CheckError
If argCount = 1 Then 'If no component specified, then simply list components
ListComponents False
ShowOutput "Components for " & databasePath, message
ElseIf Left(Wscript.Arguments(1), 1) = "*" Then 'List all components
ListComponents True
Else
QueryComponent Wscript.Arguments(1)
End If
Wscript.Quit 0
' List all table rows referencing a given component
Function QueryComponent(component)
' Get component info and format output header
Dim view, record, header, componentId
Set view = database.OpenView("SELECT `ComponentId` FROM `Component` WHERE `Component` = ?") : CheckError
Set compParam = installer.CreateRecord(1)
compParam.StringData(1) = component
view.Execute compParam : CheckError
Set record = view.Fetch : CheckError
Set view = Nothing
If record Is Nothing Then Fail "Component not in database: " & component
componentId = record.StringData(1)
header = "Component: "& component & " ComponentId = " & componentId
' List of tables with foreign keys to Component table - with subsets of columns to display
DoQuery "FeatureComponents","Feature_" '
DoQuery "PublishComponent", "ComponentId,Qualifier" 'AppData,Feature
DoQuery "File", "File,Sequence,FileName,Version" 'FileSize,Language,Attributes
DoQuery "SelfReg,File", "File_" 'Cost
DoQuery "BindImage,File", "File_" 'Path
DoQuery "Font,File", "File_,FontTitle" '
DoQuery "Patch,File", "File_" 'Sequence,PatchSize,Attributes,Header
DoQuery "DuplicateFile", "FileKey,File_,DestName" 'DestFolder
DoQuery "MoveFile", "FileKey,SourceName,DestName" 'SourceFolder,DestFolder,Options
DoQuery "RemoveFile", "FileKey,FileName,DirProperty" 'InstallMode
DoQuery "IniFile", "IniFile,FileName,Section,Key" 'Value,Action
DoQuery "RemoveIniFile", "RemoveIniFile,FileName,Section,Key" 'Value,Action
DoQuery "Registry", "Registry,Root,Key,Name" 'Value
DoQuery "RemoveRegistry", "RemoveRegistry,Root,Key,Name" '
DoQuery "Shortcut", "Shortcut,Directory_,Name,Target" 'Arguments,Description,Hotkey,Icon_,IconIndex,ShowCmd,WkDir
DoQuery "Class", "CLSID,Description" 'Context,ProgId_Default,AppId_,FileType,Mask,Icon_,IconIndex,DefInprocHandler,Argument,Feature_
DoQuery "ProgId,Class", "Class_,ProgId,Description" 'ProgId_Parent,Icon_IconIndex,Insertable
DoQuery "Extension", "Extension,ProgId_" 'MIME_,Feature_
DoQuery "Verb,Extension", "Extension_,Verb" 'Sequence,Command.Argument
DoQuery "MIME,Extension", "Extension_,ContentType" 'CLSID
DoQuery "TypeLib", "LibID,Language,Version,Description" 'Directory_,Feature_,Cost
DoQuery "CreateFolder", "Directory_" '
DoQuery "Environment", "Environment,Name" 'Value
DoQuery "ODBCDriver", "Driver,Description" 'File_,File_Setup
DoQuery "ODBCAttribute,ODBCDriver", "Driver_,Attribute,Value" '
DoQuery "ODBCTranslator", "Translator,Description" 'File_,File_Setup
DoQuery "ODBCDataSource", "DataSource,Description,DriverDescription" 'Registration
DoQuery "ODBCSourceAttribute,ODBCDataSource", "DataSource_,Attribute,Value" '
DoQuery "ServiceControl", "ServiceControl,Name,Event" 'Arguments,Wait
DoQuery "ServiceInstall", "ServiceInstall,Name,DisplayName" 'ServiceType,StartType,ErrorControl,LoadOrderGroup,Dependencies,StartName,Password
DoQuery "ReserveCost", "ReserveKey,ReserveFolder" 'ReserveLocal,ReserveSource
QueryComponent = ShowOutput(header, message)
message = Empty
End Function
' List all components in database
Sub ListComponents(queryAll)
Dim view, record, component
Set view = database.OpenView("SELECT `Component`,`ComponentId` FROM `Component`") : CheckError
view.Execute : CheckError
Do
Set record = view.Fetch : CheckError
If record Is Nothing Then Exit Do
component = record.StringData(1)
If queryAll Then
If QueryComponent(component) = vbCancel Then Exit Sub
Else
If Not IsEmpty(message) Then message = message & vbLf
message = message & component
End If
Loop
End Sub
' Perform a join to query table rows linked to a given component, delimiting and qualifying names to prevent conflicts
Sub DoQuery(table, columns)
Dim view, record, columnCount, column, output, header, delim, columnList, tableList, tableDelim, query, joinTable, primaryKey, foreignKey, columnDelim
On Error Resume Next
tableList = Replace(table, ",", "`,`")
tableDelim = InStr(1, table, ",", vbTextCompare)
If tableDelim Then ' need a 3-table join
joinTable = Right(table, Len(table)-tableDelim)
table = Left(table, tableDelim-1)
foreignKey = columns
Set record = database.PrimaryKeys(joinTable)
primaryKey = record.StringData(1)
columnDelim = InStr(1, columns, ",", vbTextCompare)
If columnDelim Then foreignKey = Left(columns, columnDelim - 1)
query = " AND `" & foreignKey & "` = `" & primaryKey & "`"
End If
columnList = table & "`." & Replace(columns, ",", "`,`" & table & "`.`")
query = "SELECT `" & columnList & "` FROM `" & tableList & "` WHERE `Component_` = ?" & query
If database.TablePersistent(table) <> 1 Then Exit Sub
Set view = database.OpenView(query) : CheckError
view.Execute compParam : CheckError
Do
Set record = view.Fetch : CheckError
If record Is Nothing Then Exit Do
If IsEmpty(output) Then
If Not IsEmpty(message) Then message = message & vbLf
message = message & "----" & table & " Table---- (" & columns & ")" & vbLf
End If
output = Empty
columnCount = record.FieldCount
delim = " "
For column = 1 To columnCount
If column = columnCount Then delim = vbLf
output = output & record.StringData(column) & delim
Next
message = message & output
Loop
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
Function ShowOutput(header, message)
ShowOutput = vbOK
If IsEmpty(message) Then Exit Function
If isGUI Then
ShowOutput = MsgBox(message, vbOKCancel, header)
Else
Wscript.Echo "> " & header
Wscript.Echo message
End If
End Function
Sub Fail(message)
Wscript.Echo message
Wscript.Quit 2
End Sub