Skip to content

Instantly share code, notes, and snippets.

@JohanSelmosson
Last active December 6, 2022 11:30
Show Gist options
  • Save JohanSelmosson/54843dc14084afe4f3991ac9304e43b9 to your computer and use it in GitHub Desktop.
Save JohanSelmosson/54843dc14084afe4f3991ac9304e43b9 to your computer and use it in GitHub Desktop.
Uninstaller for MSI-packages
function Get-InstalledSoftware {
[CmdletBinding()]
param (
)
$InstalledSoftware = Get-ChildItem "HKLM:\software\WOW6432Node\Microsoft\windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath }
$InstalledSoftware += Get-ChildItem "HKLM:\software\Microsoft\windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath }
foreach ($Software in $InstalledSoftware) {
if (!$($Software.DisplayName)) {
Write-Verbose "Skipping entry due to blank DisplayName"
Write-Verbose ($Software | Format-List | Out-String)
continue
}
[PSCustomObject]@{
DisplayName = $Software.DisplayName
DisplayVersion = $Software.DisplayVersion
InstallDate = $Software.InstallDate
Publisher = $Software.Publisher
Version = $Software.Version
GUID = $($Software.PsChildName | where-object {$_ -match '^{[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}}$'} )
UninstallString = $Software.UninstallString
}
}
} #End Function Get-InstalledSoftware
function TranslateExitCode ($exitcode) {
switch ($exitcode) {
0 { "Success" }
1603 { "Failed" }
1605 { "Unknown Product" }
1619 { "This installation package could not be opened" }
1639 { "Invalid Command Line" }
3010 { "Success, Reboot required" }
}
} #End of function TranlateExitCode
function Uninstall-MsiPackage {
[CmdletBinding(SupportsShouldProcess = $true)]
param (
# Displayname of Software to uninstall
[Parameter(ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "Displayname of the softwarepackage to uninstall")]
[Alias("DisplayName")]
[string[]]
$SoftwareName,
# Path to the msiexec logfile Directory.
[Parameter(
HelpMessage = "Path to Logfile Directory")]
[ValidateNotNullOrEmpty()]
[string]
$LogDirectory = $env:temp
)
begin {
if ($LogDirectory) {
if (!(Test-Path $LogDirectory)) {
try {
new-item $LogDirectory -ItemType Directory -force
}
catch {
$error[0].Exception.Message
}
}
}
}
process {
foreach ($Item in $SoftwareName) {
$MSIPackage = Get-InstalledSoftware | Where-Object { $_.DisplayName -eq $Item }
if (! $MSIPackage) { "Package with name [$SoftwareName] not found found, skipping.."; continue }
if ($MSIPackage.count -gt 1) { "Found more than one sofware package with the name [$SoftwareName], skipping.."; continue }
if (! $MSIPackage.GUID) {
Write-Host "There is no guid associated with [$SoftwareName]"
if ($MSIPackage.UninstallString) {
Write-Host "..there is an uninstall string though, you could try that instead:"
Write-Host $MSIPackage.UninstallString
continue
}
}
if ($PSCmdlet.ShouldProcess("$env:COMPUTERNAME", "Uninstalling $SoftwareName")) {
$ArgumentList = "/qn /X $($MSIpackage.GUID)"
if ($LogDirectory) {
$LogfileName = "UninstallLog-$($MSIPackage.DisplayName)-$(Get-Date -Format FileDateTimeUniversal).log"
$LogfilePath = Join-Path $LogDirectory $LogfileName
$ArgumentList = $ArgumentList + ' /L* "' + $logfilepath +""""
}
try {
$UninstallProcess = start-process -Wait -FilePath "C:\WINDOWS\system32\msiexec.exe" -ArgumentList $ArgumentList -PassThru
}
catch {
$error[0].Exception.Message
}
[PSCustomObject]@{
DisplayName = $MSIPackage.DisplayName
Version = $MSIPackage.DisplayVersion
Action = "Uninstall"
Start = $uninstallprocess.StartTime
End = $uninstallprocess.ExitTime
MsiExecArgumentList = $ArgumentList
ResultCode = $uninstallprocess.ExitCode
ResultMessage = $(translateexitcode $($uninstallprocess.ExitCode))
LogFile = $LogfilePath
}
}
}
}
end {
}
}
"NGUpdate" | Uninstall-MsiPackage -WhatIf
"NSClient++ (x64)" | Uninstall-MsiPackage -whatif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment