06 March 2017

PowerShell: Uninstall MSI by Application Name

This is now an old version. The new version can be found here

Here is a function that will uninstall an MSI installed application by the name of the app. You do not need to input the entire name either. For instance, say you are uninstalling all previous versions of Adobe Reader. Adobe Reader is always labeled Adobe Reader X, Adobe Reader XI, and so forth. This script allows you to do this without having to find out every version that is installed throughout a network and then enter an uninstaller line for each version. You just need to enter Adobe Reader as the application name and the desired switches. It will then search the name fields in the 32 and 64 bit uninstall registry keys to find the associated GUID. Finally, it will execute an msiexec.exe /x {GUID} to uninstall that version.

This is an update to the previous post on this. I dramatically improved the code to make this function much more efficient. 

NOTE: I used Sapien's PowerShell Studio to write this script that significantly simplified the process and made it a snap to write. I highly recommend this product for all PowerShell scripters!

You can download the code from my GitHub site located here

 <#  
      .SYNOPSIS  
           Uninstall MSI by Application Name  
        
      .DESCRIPTION  
           Here is a function that will uninstall an MSI installed application by the name of the app. You do not need to input the entire name either. For instance, say you are uninstalling all previous versions of Adobe Reader. Adobe Reader is always labeled Adobe Reader X, Adobe Reader XI, and so forth. You just need to enter Adobe Reader as the application name and the desired switches. It will then search the name fields in the 32 and 64 bit uninstall registry keys to find the associated GUID. Finally, it will execute an msiexec.exe /x {GUID} to uninstall that version.  
        
      .NOTES  
           ===========================================================================  
           Created with:     SAPIEN Technologies, Inc., PowerShell Studio 2017 v5.4.136  
           Created on:       3/6/2017 2:24 PM  
           Created by:       Mick Pletcher  
           Organization:  
           Filename:         UninstallMSIByName.ps1  
           ===========================================================================  
 #>  
 [CmdletBinding()]  
 param ()  
   
 function Uninstall-MSIByName {  
 <#  
      .SYNOPSIS  
           Uninstall-MSIByName  
        
      .DESCRIPTION  
           Uninstalls an MSI application using the MSI file  
        
      .PARAMETER ApplicationName  
           Display Name of the application. This can be part of the name or all of it. By using the full name as displayed in Add/Remove programs, there is far less chance the function will find more than one instance.  
        
      .PARAMETER Switches  
           MSI switches to control the behavior of msiexec.exe when uninstalling the application.  
        
      .EXAMPLE  
           Uninstall-MSIByName "Adobe Reader" "/qb- /norestart"  
        
      .NOTES  
           Additional information about the function.  
 #>  
        
      [CmdletBinding()]  
      param  
      (  
           [ValidateNotNullOrEmpty()][String]$ApplicationName,  
           [ValidateNotNullOrEmpty()][String]$Switches  
      )  
        
      #MSIEXEC.EXE  
      $Executable = $Env:windir + "\system32\msiexec.exe"  
      #Get list of all Add/Remove Programs for 32-Bit and 64-Bit  
      $Uninstall = Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall -Recurse -ErrorAction SilentlyContinue  
      If (((Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture).OSArchitecture) -eq "64-Bit") {  
           $Uninstall += Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall -Recurse -ErrorAction SilentlyContinue  
      }  
      #Find the registry containing the application name specified in $ApplicationName  
      $Key = $uninstall | foreach-object { Get-ItemProperty REGISTRY::$_ } | where-object { $_.DisplayName -like "*$ApplicationName*" }  
      If ($Key -ne $null) {  
           Write-Host "Uninstall"$Key.DisplayName"....." -NoNewline  
           #Define msiexec.exe parameters to use with the uninstall  
           $Parameters = "/x " + $Key.PSChildName + [char]32 + $Switches  
           #Execute the uninstall of the MSI  
           $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Parameters -Wait -Passthru).ExitCode  
           #Return the success/failure to the display  
           If (($ErrCode -eq 0) -or ($ErrCode -eq 3010) -or ($ErrCode -eq 1605)) {  
                Write-Host "Success" -ForegroundColor Yellow  
           } else {  
                Write-Host "Failed with error code "$ErrCode -ForegroundColor Red  
           }  
      }  
 }  
   
 Clear-Host  
 Uninstall-MSIByName -ApplicationName "Cisco Jabber" -Switches "/qb- /norestart"  
   

2 comments:

  1. Under conditions where the same software installed by two different vendors, or old version has not uninstalled when new version installed, it returns the following when $executable is echoed out
    /x {GUID} {GUID} /qr /norestart
    Failed with error code 1639

    I had to add a ForEach-object in, allowing parsing of the GUID's through the script inline.
    Add the following inbetween $key = $uninstall.... and if ($key -ne....
    $testsplit = $Key.pschildname
    $testsplit.split(" ") | ForEach-Object {
    $tsplit = $_
    then curly } out before calling the function at the bottom.

    then change the line
    $Parameters = "/x " + $Key.PSChildName + [char]32 + $Switches
    to
    $Parameters = "/x " + $tsplit + [char]32 + $Switches

    I think that was all the changes I made

    ReplyDelete
    Replies
    1. Thanks for that info. I have never run into that situation before.

      Delete