Get MSI Properties on the command line

I find it useful to be able to query MSI properties in a programmatic way on the command line. This is especially useful because the “ProductName” matches the “DisplayName” in the uninstall key of the registry, so I use this information to write relevance.

I have some python code that will give me this information, but what if I want to query this information on a client system? That is much easier to accomplish with something like VBScript which should work out of the box with no external dependencies.


See this example, which the following script was written for: http://bigfix.me/fixlet/details/3968


I created a VBScript which I call msiGetProperty.vbs

Usage: cscript /nologo msiGetProperty.vbs “PATH\FILE.MSI” [/Property:PROPERTY_NAME]

This was written with sensible defaults in mind. If you do not specify an MSI, then it looks for an MSI in the current directory. If you do not specify a property, then it will return the “ProductName”. If you rename the file to msiGetPropertyProductVersion.vbs then it will return the “ProductVersion”. Specifying the property or MSI on the command line always trumps other options.

' msiGetProperty.vbs
' Written by James Stewart ( @jgstew )
' Public Domain - use at your own risk
Const msiOpenDatabaseModeReadOnly = 0
Dim msiLib, db, view, msiPath, msiProperty, objCurrentFolder, myRegExp, matches

msiProperty = "ProductName"

'Prepare a regular expression object
Set myRegExp = New RegExp
myRegExp.IgnoreCase = True
myRegExp.Pattern = "msiGetProperty(\w).vbs"
Set matches = myRegExp.Execute( Wscript.ScriptName )

' set property retrieved based upon name of script
If 1 = matches.Count Then
	If 1 = matches.Item(0).SubMatches.Count Then
		msiProperty = myRegExp.Execute( Wscript.ScriptName ).Item(0).SubMatches(0)
	End If
End If

' http://blogs.technet.com/b/heyscriptingguy/archive/2006/04/05/how-can-i-determine-the-path-to-the-folder-where-a-script-is-running.aspx
' http://stackoverflow.com/questions/4200028/vbscript-list-all-pdf-files-in-folder-and-subfolders
Set objCurrentFolder = CreateObject("Scripting.FileSystemObject").GetFolder( CreateObject("Wscript.Shell").CurrentDirectory )

' https://technet.microsoft.com/en-us/library/ee156618.aspx
If 1 = WScript.Arguments.Unnamed.Count Then
	msiPath = WScript.Arguments.Unnamed.Item(0)
Else
	' operating on an MSI in the current folder ( if there are multiple, the last one will be used )
	For Each objFile in objCurrentFolder.Files
		If UCase( CreateObject("Scripting.FileSystemObject").GetExtensionName(objFile.name)) = "MSI" Then
			msiPath = objFile.Name
		End If
	Next
	
	If IsEmpty( msiPath ) Then
		Wscript.Echo
		Wscript.Echo "-ERROR-"
		Wscript.Echo "  Usage: msiGetProductVersion.vbs ""PATH\TO\FILE.MSI"" [/Property:NAME_OF_MSI_PROPERTY]"
		Wscript.Quit
	End If
End If

' http://stackoverflow.com/questions/4100506/check-if-an-object-exists-in-vbscript
'If WScript.Arguments.Named.Count = 1 Then
If NOT IsEmpty( WScript.Arguments.Named.Item("Property") ) Then
	msiProperty = WScript.Arguments.Named.Item("Property")
End If

Set msiLib = CreateObject("WindowsInstaller.Installer")
Set db = msiLib.OpenDataBase(msiPath, msiOpenDatabaseModeReadOnly)
Set view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = '" & msiProperty & "'")
view.Execute()

Wscript.Echo view.Fetch().StringData(1)

Related:

1 Like