overhaul Uninstall-MSI for pipeline input

This commit is contained in:
2023-08-23 13:56:04 -04:00
parent b52984ff32
commit 70a7ddb75d
+52 -34
View File
@@ -801,53 +801,71 @@ Function Get-GUIDFromMSIUninstallString ([string]$str) {
Return $str.Substring($start, $end - $start)
}
Function Uninstall-MSI ([Parameter(ValueFromPipeline=$true)][string]$APP_NAME) {
Function Uninstall-MSI ([Parameter(ValueFromPipeline=$true)][string[]]$APP_NAMES) {
PROCESS {
# Get all of the uninstall registry keys
$UNINSTALL_KEYS = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
$UNINSTALL_KEYS += Get-ChildItem -Path HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
# Get all of the uninstall registry keys
$UNINSTALL_KEYS = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
$UNINSTALL_KEYS += Get-ChildItem -Path HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
# Array to store custom objects about each installed MSI app
$INSTALLED_APPS = @()
# Track whether an app was uninstalled or not
$PRODUCTUNINSTALLED = $false
Foreach ( $reg in $UNINSTALL_KEYS ) {
# Get the uninstall key
$REG_PROPERTY = Get-ItemProperty -Path $reg.PSPath
Foreach ( $reg in $UNINSTALL_KEYS ) {
# Get the uninstall key
$REG_PROPERTY = Get-ItemProperty -Path $reg.PSPath
# Guards to prevent working with incompatible apps
If ( [string]::IsNullOrEmpty($REG_PROPERTY.UninstallString) -and [string]::IsNullOrEmpty($REG_PROPERTY.ModifyPath) ) { Continue }
# Get the display name of the app
$DISPLAY_NAME = $REG_PROPERTY.DisplayName
# Determine if the app is installed via MSI
If ( $REG_PROPERTY.WindowsInstaller -eq 1 ) { $UNINSTALL_SUPPORTED = $true } Else { $UNINSTALL_SUPPORTED = $false }
# Get the UninstallString
$UNINSTALLSTRING = $REG_PROPERTY.UninstallString
# 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) }
# Get the ModifyPath
$MODIFYPATH = $REG_PROPERTY.ModifyPath
# Get the product code from the ModifyPath
ElseIf ( ![string]::IsNullOrEmpty($REG_PROPERTY.ModifyPath) -and $UNINSTALL_SUPPORTED ) { $PRODUCT_CODE = $(Get-GUIDFromMSIUninstallString -str $REG_PROPERTY.ModifyPath) }
# Make sure the DisplayName matches what we're looking for
If ( $DISPLAY_NAME -ilike $APP_NAME ) {
# Make sure the software was installed using an MSI
If ( $REG_PROPERTY.WindowsInstaller -eq 1 ) {
# Get the product code from the UninstallString
If ( $UNINSTALLSTRING ) { $PRODUCT_CODE = $(Get-GUIDFromMSIUninstallString -str $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 ( $MODIFYPATH ) { $PRODUCT_CODE = $(Get-GUIDFromMSIUninstallString -str $MODIFYPATH) }
$customObject = [PSCustomObject]@{
UninstallSupported = $UNINSTALL_SUPPORTED
DisplayName = $REG_PROPERTY.DisplayName
UninstallString = $REG_PROPERTY.UninstallString
ModifyPath = $REG_PROPERTY.ModifyPath
ProductCode = $PRODUCT_CODE
}
$INSTALLED_APPS += $customObject
}
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 }
$DisplayName = $installed_app.DisplayName
$UninstallString = $installed_app.UninstallString
$ProductCode = $installed_app.ProductCode
# Print out uninstall string for unsupported apps
If ( $installed_app.UninstallSupported -eq $false ) {
LogMsg "Cannot uninstall ""${DisplayName}""`n UninstallString: ${UninstallString}"
Continue
}
# Uninstall the app
If ( $PRODUCT_CODE ) {
LogMsg "Uninstalling ${DISPLAY_NAME} ${PRODUCT_CODE}"
$arguments = '/X{' + $PRODUCT_CODE + '} /qn /norestart'
Try { Start-Process -FilePath "msiexec.exe" -ArgumentList $arguments -Wait ; $PRODUCTUNINSTALLED = $true }
Catch { LogErr $_.Exception.Message }
}
}
Else {
LogMsg "Cannot uninstall ""${DISPLAY_NAME}""`n UninstallString: ${UNINSTALLSTRING}"
LogMsg "Uninstalling ""${DisplayName}"" with product code: ${ProductCode}"
$arguments = '/X{' + $ProductCode + '} /qn /norestart'
Try { Start-Process -FilePath "msiexec.exe" -ArgumentList $arguments -Wait }
Catch { LogErr $_.Exception.Message }
}
}
}
If ( $PRODUCTUNINSTALLED -eq $false ) { LogMsg "No product matching ${APP_NAME} was found"}
}
Setup-MSPDirectories