diff --git a/Tools.ps1 b/Tools.ps1 index 267f42b..f98a3b9 100644 --- a/Tools.ps1 +++ b/Tools.ps1 @@ -892,55 +892,73 @@ Function Get-GUIDFromMSIUninstallString ([string]$str) { Return $retval } -Function Uninstall-MSI ([Parameter(ValueFromPipeline=$true)][string[]]$APP_NAMES) { - PROCESS { +Function Uninstall-MSI { + param( + [Parameter(ValueFromPipeline=$true,Mandatory=$true)][string[]]$APP_NAMES, + [Parameter(ValueFromPipeline=$false,Mandatory=$false)][switch]$Match, + [Parameter(ValueFromPipeline=$false,Mandatory=$false)][switch]$IncludeNonMSI + ) + BEGIN { # Get all of the uninstall registry keys $UNINSTALL_KEYS = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue $UNINSTALL_KEYS += Get-ChildItem -Path HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall -ErrorAction SilentlyContinue # Exit if we can't find any software at all - If ( $UNINSTALL_KEYS.Length -eq 0 ) { Write-Error "Attempted to uninstall ${APP_NAMES} but could not find any installed apps in the Windows Registry" ; Return } + If ( $UNINSTALL_KEYS.Length -eq 0 ) { Write-Error "Could not find any installed apps in the Windows Registry" ; Return } - # Array to store custom objects about each installed MSI app + # Array to store custom objects about each installed MSI app $INSTALLED_APPS = @() Foreach ( $reg in $UNINSTALL_KEYS ) { # Get the uninstall key $REG_PROPERTY = Get-ItemProperty -Path $reg.PSPath - # Guards to prevent working with incompatible apps + # Skip apps missing both the UninstallString and ModifyPath If ( [string]::IsNullOrEmpty($REG_PROPERTY.UninstallString) -and [string]::IsNullOrEmpty($REG_PROPERTY.ModifyPath) ) { Continue } # Determine if the app is installed via MSI - If ( $REG_PROPERTY.WindowsInstaller -eq 1 ) { $UNINSTALL_SUPPORTED = $true } Else { $UNINSTALL_SUPPORTED = $false } + If ( $REG_PROPERTY.WindowsInstaller -eq 1 ) { - # Get the product code from the UninstallString or ModifyPath if the app is installed via MSI - [string]$PRODUCT_CODE = $null - If ( ![string]::IsNullOrEmpty($REG_PROPERTY.UninstallString) -and $UNINSTALL_SUPPORTED ) { $PRODUCT_CODE = $(Get-GUIDFromMSIUninstallString -str $REG_PROPERTY.UninstallString) } + $MSI = $true - # Get the product code from the ModifyPath - ElseIf ( ![string]::IsNullOrEmpty($REG_PROPERTY.ModifyPath) -and $UNINSTALL_SUPPORTED ) { $PRODUCT_CODE = $(Get-GUIDFromMSIUninstallString -str $REG_PROPERTY.ModifyPath) } + # Get the product code from the UninstallString or ModifyPath if the app is installed via MSI + If ( ![string]::IsNullOrEmpty($REG_PROPERTY.UninstallString) ) { $PRODUCT_CODE = $(Get-GUIDFromMSIUninstallString -str $REG_PROPERTY.UninstallString) } - # Additional guard to prevent adding an app with no product code - If ( [string]::IsNullOrEmpty($PRODUCT_CODE) ) { Continue } + # Get the product code from the ModifyPath + ElseIf ( ![string]::IsNullOrEmpty($REG_PROPERTY.ModifyPath) ) { $PRODUCT_CODE = $(Get-GUIDFromMSIUninstallString -str $REG_PROPERTY.ModifyPath) } + + # Don't add an app with an unknown product code + If ( [string]::IsNullOrEmpty($PRODUCT_CODE) ) { Continue } + + } Else { $MSI = $false } + + # Get a usable name for the entry + If ( $REG_PROPERTY.DisplayName) $customObject = [PSCustomObject]@{ - UninstallSupported = $UNINSTALL_SUPPORTED + MSI = $MSI DisplayName = $REG_PROPERTY.DisplayName UninstallString = $REG_PROPERTY.UninstallString ModifyPath = $REG_PROPERTY.ModifyPath ProductCode = $PRODUCT_CODE } + # Cleanup object properties + If ( $customObject.) + $INSTALLED_APPS += $customObject } - + } + PROCESS { Foreach ( $app in $APP_NAMES ) { Foreach ( $installed_app in $INSTALLED_APPS ) { - # Make sure the DisplayName matches what we're looking for - If ( !($installed_app.DisplayName -ilike $app) ) { Continue } + # Do not add apps which name does not match the one we're looking for + Switch ( $Match ) { + $true { If ( !($installed_app.DisplayName -match $app) ) { Continue } } + $false { If ( !($installed_app.DisplayName -ilike $app) ) { Continue } } + } $DisplayName = $installed_app.DisplayName $UninstallString = $installed_app.UninstallString