Public/Uninstall-vlApplication.ps1
Function Uninstall-vlApplication { <# .SYNOPSIS Uninstalls an application either locally or remotely .PARAMETER Computer A computer name or a list of computer names where the application should be uninstalled. Defaults to the local computer. Pipeline input is supported. .PARAMETER UninstallString The command to run to uninstall the application. Valid examples are: - MsiExec.exe /X{DC87320F-6CBA-3BC0-BC1E-65AF3961076C} - If 'MsiExec.exe' is detected the necessary silent parameter '/qn' is added automatically. - "`"C:\ProgramData\Package Cache\{ce085a78-074e-4823-8dc1-8a721b94b76d}\vcredist_x86.exe`" /uninstall /quiet" - Note that quotation marks in paths need to be escaped like above .PARAMETER Credential Specifies the credentials when uninstallation on a remote computer is desired. .EXAMPLE PS C:\> Get-vlInstalledApplication -Computer PC1 -Name 'Google Chrome' | Uninstall-vlApplication -ValidExitCodes 0,3010,1 Gets the uninstall string of an application from a remote machine and uninstall it there. Valid exit codes are 0, 3010, and 1. .EXAMPLE PS C:\> $UninstallString = (Get-vlInstalledApplication -Computer PC1 -Name 'Google Chrome').UninstallString PS C:\> PC1', 'PC2', 'PC3' | Uninstall-vlApplication -UninstallString $UninstallString -RebootAfterSuccess Gets the uninstall string of an application from a remote machine and uninstalls it on multiple machines. Reboots every machine if uninstallation was successful. .NOTES Author: vast limits GmbH #> [OutputType([System.String])] [Cmdletbinding()] Param( [Parameter(ValueFromPipelineByPropertyName = $True)] [Alias('Computername', 'PSComputername', '__Server', 'CN')] [System.String[]]$Computer = $env:COMPUTERNAME, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $True)] [Alias('QuietUninstallString')] [System.String]$UninstallString, [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential, [Parameter()] [switch]$RebootAfterSuccess, [Parameter()] [int32[]]$ValidExitCodes = @("0", "3010") ) Begin { $ErrorActionPreference = 'Stop' try { # Initialize output $Results = @() } catch { Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } } Process { try { $scriptblock = { If ($args[0].ContainsKey('Verbose')) { $VerbosePreference = 'Continue' } $args[0].GetEnumerator() | ForEach-Object { New-Variable -Name $_.Key -Value $_.Value } Write-Verbose "Reset variables based on uninstaller" if ($UninstallString -match 'msiexec') { $Uninstaller = 'msiexec.exe' $Uninstallstring = $UninstallString -replace 'msiexec.exe', '' -replace 'msiexec', '' -replace '/i', '' -replace '/qn', '' -replace '/qb', '' -replace '/quiet', '' -replace '/passive', '' -replace '/qr', '' -replace '/qf', '' $Uninstallstring = $UninstallString + ' ' + '/qn' Write-Verbose "Start uninstallation" Write-Verbose "Uninstaller: $Uninstaller" Write-Verbose "Uninstall arguments: $UninstallString" $ExitCode = (Start-Process -FilePath $Uninstaller -ArgumentList $UninstallString -Wait -PassThru).ExitCode } elseif ($UninstallString -match '.exe') { Write-Verbose "Start uninstallation" Write-Verbose "Uninstall command: $UninstallString" & $UninstallString | Out-Null $ExitCode = $LASTEXITCODE } else { Throw "Error: Only '.msi' and '.exe' files are supported. If you need to run a script to uninstall something please use 'Install-vlApplication'. - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } Write-Output -InputObject $ExitCode } if ($Computer -eq $env:COMPUTERNAME) { # running locally $c = $env:COMPUTERNAME $ExitCode = Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $PSBoundParameters -Verbose:$VerbosePreference # after installation if ($ValidExitCodes -notcontains $ExitCode) { $Results += [PSCustomObject]@{Computer = $c; Success = $false } Write-Error "Installation not successful. Exit code: $ExitCode" } else { Write-Verbose "Installation successful. Exit code: $ExitCode" $Results += [PSCustomObject]@{Computer = $c; Success = $true } If ($RebootAfterSuccess) { Write-Verbose "Reboot desired by parameter. Reboot $c." Restart-Computer -ComputerName $c -Timeout 30 } } } else { # running remotely foreach ($c in $Computer) { Write-Verbose "Test connectivitiy to computer $c" if (Test-vlConnection -Computer $c) { $ExitCode = Invoke-Command -ComputerName $c -ScriptBlock $scriptBlock -ArgumentList $PSBoundParameters -Credential $Credential -Verbose:$VerbosePreference } # after installation if ($ValidExitCodes -notcontains $ExitCode) { $Results += [PSCustomObject]@{Computer = $c; Success = $false } Write-Error "Installation not successful. Exit code: $ExitCode" } else { Write-Verbose "Installation successful. Exit code: $ExitCode" $Results += [PSCustomObject]@{Computer = $c; Success = $true } If ($RebootAfterSuccess) { Write-Verbose "Reboot desired by parameter. Reboot $c." Restart-Computer -ComputerName $c -Timeout 30 } } } } } catch { $Results += [PSCustomObject]@{Computer = $c; Result = $false } Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } finally { } } end { Write-Output $Results } } |