PowerShell 4.0 – Get-MSIProperties

Anyone who uses SCCM for application deployments knows the frustration of having to find MSI product codes.

There are a few ways to make this process easier. My preferred method has always been to use the Detection Method tab to extract the product code that I can then copy/paste into the other tabs but when you are creating large amounts of applications this can be a very slow process.

So using PowerShell we can get a list of MSI properties without having to install the MSI or use additional steps in SCCM.

The function in this script can also be used in bigger scripts such as scripts to automate application installation (Something I will post about shortly)

I would like to thank Nickolaj Andersen (http://www.scconfigmgr.com/) for some of the code snippets


###############################################################################
####                                                                       ####
####                                                                       ####
####                          Get-MSIProperties                            ####
####                            Version 1.0.0                              ####
####                       Created by: Liam Matthews                       ####
####                                                                       ####
####                                                                       ####
###############################################################################

################################Release notes##################################
####                                                                       ####
################################### 1.0.0 #####################################
#### - Initial release                                                     ####
####                                                                       ####
###############################################################################

<#
.SYNOPSIS
    Get-MSIProperties retrieves all properties for the specified MSI(s)

.DESCRIPTION
    Get-MSIProperties retrieves all properties for the specified MSI(s)

.PARAMETER File
    Single msi file. Can be full path ot file name if in current location

    Example: C:\Temp\My.msi
    Example: my.msi

.PARAMETER Folder
    Specify a folder name. The all msi files is any subfolders will be included

    Example: C:\Temp

.PARAMETER Output
    Outputs the data to a html file in the script launch folder

.PARAMETER Log
    Outputs script running data to log file

.EXAMPLE
    Get-MSIProperties -File My.msi

    FileName                  Manufacturer ProductName               ProductVersion ProductLanguage ProductCode
    --------                  ------------ -----------               -------------- --------------- -----------
    H:\Software\7z920-x64.msi  Igor Pavlov  7-Zip 9.20 (x64 edition)  9.20.00.0      1033            {23170F69-40C1-2702-0920-000001000000}

    The above command gathers msi properties on the specified file 

.EXAMPLE
    Get-MSIProperties -Folder C:\Temp -Output

    FileName                                   Path                                               Manufacturer  ProductName       ProductVersion ProductLanguage ProductCode
    --------                                   ----                                               ------------  -----------       -------------- --------------- -----------
    GoogleChromeStandaloneEnterprise.msi       H:\Software\Google\Chrome                           Google, Inc.  Google Chrome     65.240.16509   1033            {80E666DA-3CC1-3476-9968-029D9F1FEB8F}
    Google Chrome Enterprise 32.0.1700.107.msi H:\Software\Google\Chrome\Enterprise\32.0.1700.107  Google, Inc.  Google Chrome     65.169.107     1033            {56B708CC-28A0-3CFC-A83B-BE70E5C4EA18}
    Google Chrome Enterprise 33.0.1750.154.msi H:\Software\Google\Chrome\Enterprise\33.0.1750.154  Google, Inc.  Google Chrome     65.181.32922   1033            {FBD50733-2ABE-3D23-88B4-7B0C0A0ADDA0}
    Google Earth.msi                           H:\Software\Google\Earth\Free\7.1.2.2041            Google        Google Earth      7.1.2.2041     1033            {4D2A6330-2F8B-11E3-9C40-B8AC6F97B88E}
    Google Earth Pro.msi                       H:\Software\Google\Earth\Pro\7.1.2.2041             Google        Google Earth Pro  7.1.2.2041     1033            {44FC61F0-2F8A-11E3-8CAE-B8AC6F97B88E}         

    The above command checks if the specified HotFixID is installed on the list of computers contained in a text file and outputs the results to a html file in the script launch folder

.NOTES
    Version 1.0.0
    Created by Liam Matthews
    Credit to Nickolaj Andersen for code snippets (http://www.scconfigmgr.com/)
#>

[CmdletBinding(DefaultParameterSetName="File")]
Param
(
    # Argument: File
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="File",Position=0)]
    [String]$File,

    # Argument: Folder
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="Folder",Position=0)]
    [String]$Folder = ".\",

    # Argument: Output
    [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
    [Switch]$Output

)

#Declaring initial variables
$ScriptInfo = Get-PSCallStack
$StartTime = Get-Date -Format "HH:mm:ss.fff"
$StartDate = Get-Date -Format "MM-dd-yyyy"
$StartDateTime = Get-Date -Format "HHmmss"
$TZbias = (Get-WmiObject -Query "Select Bias from Win32_TimeZone").bias

#Function for fetching MSI properties
Function Get-MSIProperty ([string]$Path,[string]$Property)
{
    $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
    $comObjWI = New-Object -ComObject WindowsInstaller.Installer
    $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$comObjWI,@("$Path",0))
    $Query = "SELECT Value FROM Property WHERE Property = '$Property'"
    $View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query))
    $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
    $Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null)
    $Value = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1)

    Return $Value
}

#Clear output table
$Results = @()

#Action if file specified
IF ($File)
{
    $Manufacturer = Get-MSIProperty -Path $File -Property "Manufacturer"
    $ProductName = Get-MSIProperty -Path $File -Property "ProductName"
    $ProductVersion = Get-MSIProperty -Path $File -Property "ProductVersion"
    $ProductLanguage = Get-MSIProperty -Path $File -Property "ProductLanguage"
    $ProductCode = Get-MSIProperty -Path $File -Property "ProductCode"

    #Build results table
    $Results += New-Object PSObject -Property ([ordered]@{
        "FileName" = "$File"
        "Manufacturer" = "$Manufacturer"
        "ProductName" = "$ProductName"
        "ProductVersion" = "$ProductVersion"
        "ProductLanguage" = "$ProductLanguage"
        "ProductCode" = "$ProductCode"
    })
}
#Action if folder specified
ELSE
{
    #Searching for MSI files in folder
    $AllMSIFiles = Get-ChildItem $Folder -Recurse -Filter *.msi

    #Run action for each MSI found
    foreach ($MSIFullName in $AllMSIFiles)
    {
        $Manufacturer = Get-MSIProperty -Path $MSIFullName.FullName -Property "Manufacturer"
        $ProductName = Get-MSIProperty -Path $MSIFullName.FullName -Property "ProductName"
        $ProductVersion = Get-MSIProperty -Path $MSIFullName.FullName -Property "ProductVersion"
        $ProductLanguage = Get-MSIProperty -Path $MSIFullName.FullName -Property "ProductLanguage"
        $ProductCode = Get-MSIProperty -Path $MSIFullName.FullName -Property "ProductCode"

        #Build results table
        $Results += New-Object PSObject -Property ([ordered]@{
            "FileName" = $MSIFullName.Name
            "Path" = $MSIFullName.Directory
            "Manufacturer" = "$Manufacturer"
           "ProductName" = "$ProductName"
            "ProductVersion" = "$ProductVersion"
            "ProductLanguage" = "$ProductLanguage"
            "ProductCode" = "$ProductCode"
        })

    }
}

#Output to file or screen
IF ($Output)
{
        #Output to file
        $Results | ConvertTo-Html | Out-File MSIProperties-$StartDateTime.html
}
ELSE
{
    #Output to screen
    $Results | Format-Table
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s