The built-in PowerShell Package Manager is unreliable when it comes to installing and removing software packages in the MSI format. However, there is an excellent open source Windows Installer PowerShell module provided by Heath Stewart for performing many tasks with MSI installers and MSI-based installations.

You can install the module from the PowerShell Gallery using the following command:

Install-Module MSI

Installing MSIs ^

While you can use the standard msiexec command line for installing your MSIs, the command below is built with PowerShell in mind. This means it always executes silently and returns progress, warnings, and errors directly to the PowerShell pipeline.

Install-MSIProduct .\example.msi

The same features apply to the other cmdlets provided for modifying or removing existing installations: Install-MSIPatch, Repair-MSIProduct, Uninstall-MSIPatch, and Uninstall-MSIProduct.

Getting information ^

Sometimes you have to get information from the MSI file without installing the program. You can easily accomplish this using the following command:

Get-MSIProperty -Path .\example.msi

If we run this against an MSI for installing the Microsoft Deployment Toolkit (MDT), we get the following results:

Information displayed from the Get MSIProperty command

Information displayed from the Get MSIProperty command

Get-MSIProductInfo easily retrieves information on existing installations:

Get-MSIProductInfo | where {$_.Productname -like "*sharepoint*"}

The above example will show us all the installations with a product name matching SharePoint.

Results from the Get MSIProductInfo command

Results from the Get MSIProductInfo command

Uninstalling MSIs ^

We can also pipe the results of this command to other commands so we can modify existing installations.

Get-MSIProductInfo | where {$_.Productname -like "*sharepoint*"} | Uninstall-MSIProduct

The above example removes all installed products on the PC that have a product name matching SharePoint.

Generating DSC configurations ^

A simple use case example is generating a DSC configuration. Let's say you need to script a configuration for servers using the Microsoft Desired State Configuration Package resource. The documentation specifies that we have three required parameters: Name (package name), Path (location of the package), and ProductId (unique identifier).

The ProductId and the Name both need to come from the MSI for the DSC to work properly. Depending on the number of MSIs you have, this could quickly become a pain. Using the MSI module though, we can quickly loop through all the MSIs in a directory and automatically create our configuration. We're using code to write our code!

Get-ChildItem *.msi | foreach {
    $ProductName = (Get-MSIProperty -Path $_.FullName -Property ProductName).Value
    $ProductCode = (Get-MSIProperty -Path $_.FullName -Property ProductCode).Value
    $DSCPackagename = $_.Name.TrimEnd(".msi")
    $MSIFileName = $_.Name
@"
    package $DSCPackagename
    {
        Name = '$ProductName'
        Path = '\\MyPackageShare\$MSIFileName'
        ProductId = '$ProductCode'
        Arguments = '/qn'
        Ensure = 'Present'
    }
"@
}

Running this simple script in a directory with a couple of MDT MSIs yields the following configuration script ready for copying and pasting into an existing configuration:

Subscribe to 4sysops newsletter!

package MicrosoftDeploymentToolkit2013_x64
{
    Name = 'Microsoft Deployment Toolkit 2013 Update 2 (6.3.8330.1000)'
    Path = '\\MyPackageShare\MicrosoftDeploymentToolkit2013_x64.msi'
    ProductId = '{F172B6C7-45DD-4C22-A5BF-1B2C084CADEF}'
    Arguments = '/qn'
    Ensure = 'Present'
}
package MicrosoftDeploymentToolkit_x64
{
    Name = 'Microsoft Deployment Toolkit (6.3.8443.1000)'
    Path = '\\MyPackageShare\MicrosoftDeploymentToolkit_x64.msi'
    ProductId = '{9547DE37-4A70-4194-97EA-ACC3E747254B}'
    Arguments = '/qn'
    Ensure = 'Present'
}
avataravatar