Skip to content

Instantly share code, notes, and snippets.

@Bill-Stewart
Created September 3, 2024 17:20
Show Gist options
  • Save Bill-Stewart/f3623647f4e022c28ab278337610ba0f to your computer and use it in GitHub Desktop.
Save Bill-Stewart/f3623647f4e022c28ab278337610ba0f to your computer and use it in GitHub Desktop.
// MSIInfo.js
// Written by Bill Stewart (bstewart AT iname.com)
// Outputs properties from an MSI database.
var SCRIPT_NAME = "MSIInfo.js";
// This array specifies the property names the script will handle.
var VALID_PROPERTIES = ["Manufacturer","ProductName","ProductVersion",
"ProductCode","UpgradeCode"];
var MB_ICONERROR = 0x10,
MB_ICONINFORMATION = 0x40;
// Returns the script host's name (cscript.exe or wscript.exe).
function scriptHost() {
return WScript.FullName.substring(WScript.Path.length + 1).toLowerCase();
}
// Outputs the specified string depending on which script host is active.
// If the script host is wscript.exe, the type parameter specifies the type
// of dialog box to use. The type parameter is ignored if the script host
// is cscript.exe.
function echo(string,type) {
if ( scriptHost() == "cscript.exe" )
WScript.Echo(string);
else {
var wshShell = new ActiveXObject("WScript.Shell");
wshShell.Popup(string,0,"MSI Information",type);
}
}
// Returns the specified array as a space-delimited string.
function arrayToString(theArray) {
var result = "";
for ( var n = 0; n < theArray.length; n++ )
result += result == "" ? theArray[n] : " " + theArray[n];
return result;
}
// Outputs a usage message for the user.
function usage() {
echo("Displays information about an MSI database.\r\n" +
"\r\n" +
"Usage: " + SCRIPT_NAME + " <msifile> [<propertyname>]\r\n" +
"\r\n" +
"If specified, <propertyname> must be one of the following values:\r\n" +
"\r\n" +
arrayToString(VALID_PROPERTIES) + "\r\n" +
"\r\n" +
"Property names must be spelled with the correct case. Without a\r\n" +
"property name, all property values are displayed.",
MB_ICONINFORMATION);
WScript.Quit(0);
}
// Returns true if the specified item is an element in the array, or false
// otherwise.
function itemInArray(theItem,theArray) {
for ( var n = 0; n < theArray.length; n++ )
if ( theItem == theArray[n] )
return true;
return false;
}
// Returns the specified number as a hex string.
function hex(n) {
return n < 0 ? (n + Math.pow(2,32)).toString(0x10).toUpperCase() :
n.toString(0x10).toUpperCase();
}
// Returns a property's value from an MSI database. If the property doesn't
// exist, returns a blank string.
function getProperty(database,property) {
var view = database.OpenView("select `Value` from `Property` where " +
"`Property` = '" + property + "'");
view.Execute();
var record = view.Fetch();
return record == null ? "" : record.StringData(1);
}
function main() {
var args = WScript.Arguments;
if ( (args.Unnamed.length == 0) || (args.Named.Exists("?")) )
usage();
var msiFile = args.Unnamed.Item(0);
// Return an error if the named MSI file doesn't exist.
var fso = new ActiveXObject("Scripting.FileSystemObject");
if ( ! fso.FileExists(msiFile) ) {
echo("File not found - " + msiFile,MB_ICONERROR);
return 2; // ERROR_FILE_NOT_FOUND
}
// Open the MSI database, or fail gracefully if an error occurs.
try {
var installer = new ActiveXObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(msiFile,0); // read-only
}
catch(err) {
echo("Error 0x" + hex(err.number) + " opening msi file",MB_ICONERROR);
return err.number;
}
// If a property name is not specified, output all properties.
if ( args.Unnamed.length == 1 ) {
var properties = VALID_PROPERTIES;
var output = "MSI file: " + msiFile;
for ( var n = 0; n < properties.length; n++ ) {
var property = getProperty(database,properties[n]);
output += "\r\n" + properties[n] + ": " + property;
}
echo(output,0);
return 0;
}
// Get the property name from the command line.
var property = args.Unnamed.Item(1);
// If the property name is not valid, output an error and exit.
if ( ! itemInArray(property,VALID_PROPERTIES) ) {
echo("Property name must be one of the following (case-sensitive):\r\n" +
"\r\n" +
arrayToString(VALID_PROPERTIES),
MB_ICONERROR);
return 87; // ERROR_INVALID_PARAMETER
}
// Output the property.
echo(getProperty(database,property),0);
return 0;
}
WScript.Quit(main());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment