16 June 2016

PowerShell: Pulling information from MSP files

Recently, I began making significant updates to one of my other scripts on here. In the process of asking questions about MSP files on Facebook PowerShell groups, it was clear to me that it would only take a few tweaks to make scripts that extract MSI data also be able to extract MSP data.

I first started out by pulling the code from stack overflow on how to extract data from an MSI. Obviously, that code did not work with an MSP. It was putting up the exception code message. When I debugged it, the script was catching on line 28. Since an MSP is just a patch, and it is still a database, I figured that same code could be adapted to read the data from the MSP. The key information that helped me what from Microsoft's Installer.OpenDatabase method webpage. The parameter values and what each value does was the key to figuring this out. The parameter value of 32 indicates the database is associated with an MSP file. As you can see at the end of line 28, there is a value of 32. That was originally a 0, which associated this script with an MSI, instead of an MSP. I suggest going to the Microsoft link above and reviewing the difference parameter values that can be used.

The script below was written for obtaining information from an MSP pertaining to Microsoft Office updates. From what I have seen in several MSPs I have looked at, they all differ in what tables are available. The table you want to look at for pulling data is called MsiPatchMetadata. There are some that do not have the MsiPatchMetadata table. This is defined on line 29. Property is what contains the list of available data fields. Below is a screenshot of Adobe Reader XI update MSP file viewed through ORCA. As you can see, there are two tables and several Property fields available.

In the script below, I have included the standard fields I have seen in most MSP files. Those fields are: Classification, Description, DisplayName, KBArticle Number, ManufacturerName, ReleaseVersion, and TargetProductName. Thanks to Sapien's PowerShell Studio, the script was a snap to write! I reviewed MSP files from many different applications my firm uses, and these were the most common, which also include Microsoft Office MSP updates. You may run into additional fields also which will require you to add them to the parameter validation set of the property variable.

I did not use any main parameters because I figure this function will likely be copied and used inside other scripts.

Here is a video I made that goes through and explains the process:

You can download the script from here:

1:  <#  
2:       .SYNOPSIS  
3:            Extract MSP information  
5:       .DESCRIPTION  
6:            This script will extract MSP file information from the metadata table. It has been written to be able to read data from a lot of different MSP files, including Microsoft Office updates and most application patches. There are some MSP files that were not populated with the metadata table, therefor no data is obtainable.   
8:       .NOTES  
9:            ===========================================================================  
10:            Created with:     SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.122  
11:            Created on:       6/15/2016 4:07 PM  
12:            Created by:       Mick Pletcher  
13:            Organization:  
14:            Filename:         MSPInfo.ps1
15:            ===========================================================================  
16:  #>  
19:  function Get-MSPFileInfo {  
20:       param  
21:       (  
22:                 [Parameter(Mandatory = $true)][IO.FileInfo]$Path,  
23:                 [Parameter(Mandatory = $true)][ValidateSet('Classification', 'Description', 'DisplayName', 'KBArticle Number', 'ManufacturerName', 'ReleaseVersion', 'TargetProductName')][string]$Property  
24:       )  
26:       try {  
27:            $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer  
28:            $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $Null, $WindowsInstaller, @($Path.FullName, 32))  
29:            $Query = "SELECT Value FROM MsiPatchMetadata WHERE Property = '$($Property)'"  
30:            $View = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($Query))  
31:            $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)  
32:            $Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)  
33:            $Value = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)  
34:            return $Value  
35:       } catch {  
36:            Write-Output $_.Exception.Message  
37:       }  
38:  }  
40:  Get-MSPFileInfo -Path "mstore-x-none.msp" -Property 'KBArticle Number'  


Post a Comment