|
| 1 | +function Uninstall-MSU { |
| 2 | + [CmdletBinding(DefaultParameterSetName='KBNumber')] |
| 3 | + Param ( |
| 4 | + [Parameter( |
| 5 | + Mandatory=$True, |
| 6 | + ParameterSetName='KBNumber' |
| 7 | + )] |
| 8 | + [string]$KBNumber, |
| 9 | + |
| 10 | + [Parameter( |
| 11 | + Mandatory=$True, |
| 12 | + ParameterSetName='MSUFile' |
| 13 | + )] |
| 14 | + [ValidatePattern("\.msu$")] |
| 15 | + [string]$PathToMSUFile, |
| 16 | + |
| 17 | + [Parameter(Mandatory=$False)] |
| 18 | + [string]$LogFilePath |
| 19 | + ) |
| 20 | + |
| 21 | + if (![bool]$(Get-Command wusa.exe -ErrorAction SilentlyContinue)) { |
| 22 | + Write-Error "Unable to find wusa.exe! Halting!" |
| 23 | + $global:FunctionResult = "1" |
| 24 | + return |
| 25 | + } |
| 26 | + |
| 27 | + if ($KBNumber) { |
| 28 | + $Arguments = "/uninstall /kb:$KBNumber /quiet /norestart" |
| 29 | + if (!$LogFilePath) { |
| 30 | + $LogFilePath = "$HOME\wusaKB$KBNumber.log" |
| 31 | + } |
| 32 | + |
| 33 | + $Arguments = $Arguments + " /log:`"$LogFilePath`"" |
| 34 | + } |
| 35 | + if ($PathToMSUFile) { |
| 36 | + if (!$(Test-Path $PathToMSUFile)) { |
| 37 | + Write-Error "The path $PathToMSUFile was not found! Halting!" |
| 38 | + $global:FunctionResult = "1" |
| 39 | + return |
| 40 | + } |
| 41 | + |
| 42 | + $MSUFileItem = Get-Item $PathToMSUFile |
| 43 | + |
| 44 | + $Arguments = "/uninstall `"$PathToMSUFile`" /quiet /norestart" |
| 45 | + if (!$LogFilePath) { |
| 46 | + $LogFilePath = "$HOME\wusaKB$($MSUFileItem.BaseName).log" |
| 47 | + } |
| 48 | + |
| 49 | + $Arguments = $Arguments + " /log:`"$LogFilePath`"" |
| 50 | + } |
| 51 | + |
| 52 | + $ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo |
| 53 | + #$ProcessInfo.WorkingDirectory = $BinaryPath | Split-Path -Parent |
| 54 | + $ProcessInfo.FileName = $(Get-Command wusa.exe).Source |
| 55 | + $ProcessInfo.RedirectStandardError = $true |
| 56 | + $ProcessInfo.RedirectStandardOutput = $true |
| 57 | + $ProcessInfo.UseShellExecute = $false |
| 58 | + $ProcessInfo.Arguments = $Arguments |
| 59 | + $Process = New-Object System.Diagnostics.Process |
| 60 | + $Process.StartInfo = $ProcessInfo |
| 61 | + $Process.Start() | Out-Null |
| 62 | + # Below $FinishedInAlottedTime returns boolean true/false |
| 63 | + # Wait 30 seconds for wusa to finish... |
| 64 | + $FinishedInAlottedTime = $Process.WaitForExit(30000) |
| 65 | + if (!$FinishedInAlottedTime) { |
| 66 | + $Process.Kill() |
| 67 | + } |
| 68 | + $stdout = $Process.StandardOutput.ReadToEnd() |
| 69 | + $stderr = $Process.StandardError.ReadToEnd() |
| 70 | + $AllOutput = $stdout + $stderr |
| 71 | + |
| 72 | + # Check the log to make sure there weren't any errors |
| 73 | + # NOTE: Get-WinEvent cmdlet does NOT work consistently on all Windows Operating Systems... |
| 74 | + Write-Host "Reviewing wusa.exe logs..." |
| 75 | + $EventLogReader = [System.Diagnostics.Eventing.Reader.EventLogReader]::new($LogFilePath, [System.Diagnostics.Eventing.Reader.PathType]::FilePath) |
| 76 | + [System.Collections.ArrayList]$EventsFromLog = @() |
| 77 | + |
| 78 | + $Event = $EventLogReader.ReadEvent() |
| 79 | + $null = $EventsFromLog.Add($Event) |
| 80 | + while ($Event -ne $null) { |
| 81 | + $Event = $EventLogReader.ReadEvent() |
| 82 | + $null = $EventsFromLog.Add($Event) |
| 83 | + } |
| 84 | + |
| 85 | + if ($EventsFromLog.LevelDisplayName -contains "Error") { |
| 86 | + $ErrorRecord = $EventsFromLog | Where-Object {$_.LevelDisplayName -eq "Error"} |
| 87 | + $ProblemDetails = $ErrorRecord.Properties.Value | Where-Object {$_ -match "[\w]"} |
| 88 | + $ProblemDetailsString = $ProblemDetails[0..$($ProblemDetails.Count-2)] -join ": " |
| 89 | + |
| 90 | + if ($PathToMSUFile) { |
| 91 | + $ErrMsg = "wusa.exe failed to uninstall '$PathToMSUFile' due to '$ProblemDetailsString'. " + |
| 92 | + "This could be because of a pending restart. Please restart $env:ComputerName and try the " + |
| 93 | + "$($MyInvocation.MyCommand.Name) function again." |
| 94 | + } |
| 95 | + if ($KBNumber) { |
| 96 | + $ErrMsg = "wusa.exe failed to uninstall '$KBNumber' due to '$ProblemDetailsString'. " + |
| 97 | + "This could be because of a pending restart. Please restart $env:ComputerName and try the " + |
| 98 | + "$($MyInvocation.MyCommand.Name) function again." |
| 99 | + } |
| 100 | + Write-Error $ErrMsg |
| 101 | + $global:FunctionResult = "1" |
| 102 | + return |
| 103 | + } |
| 104 | + else { |
| 105 | + $Output = "Success" |
| 106 | + } |
| 107 | + |
| 108 | + $Output |
| 109 | +} |
| 110 | +# SIG # Begin signature block |
| 111 | +# MIIMiAYJKoZIhvcNAQcCoIIMeTCCDHUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB |
| 112 | +# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR |
| 113 | +# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUopnOEHwqbnMFUIJby597TmxT |
| 114 | +# 6Fmgggn9MIIEJjCCAw6gAwIBAgITawAAAB/Nnq77QGja+wAAAAAAHzANBgkqhkiG |
| 115 | +# 9w0BAQsFADAwMQwwCgYDVQQGEwNMQUIxDTALBgNVBAoTBFpFUk8xETAPBgNVBAMT |
| 116 | +# CFplcm9EQzAxMB4XDTE3MDkyMDIxMDM1OFoXDTE5MDkyMDIxMTM1OFowPTETMBEG |
| 117 | +# CgmSJomT8ixkARkWA0xBQjEUMBIGCgmSJomT8ixkARkWBFpFUk8xEDAOBgNVBAMT |
| 118 | +# B1plcm9TQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCwqv+ROc1 |
| 119 | +# bpJmKx+8rPUUfT3kPSUYeDxY8GXU2RrWcL5TSZ6AVJsvNpj+7d94OEmPZate7h4d |
| 120 | +# gJnhCSyh2/3v0BHBdgPzLcveLpxPiSWpTnqSWlLUW2NMFRRojZRscdA+e+9QotOB |
| 121 | +# aZmnLDrlePQe5W7S1CxbVu+W0H5/ukte5h6gsKa0ktNJ6X9nOPiGBMn1LcZV/Ksl |
| 122 | +# lUyuTc7KKYydYjbSSv2rQ4qmZCQHqxyNWVub1IiEP7ClqCYqeCdsTtfw4Y3WKxDI |
| 123 | +# JaPmWzlHNs0nkEjvnAJhsRdLFbvY5C2KJIenxR0gA79U8Xd6+cZanrBUNbUC8GCN |
| 124 | +# wYkYp4A4Jx+9AgMBAAGjggEqMIIBJjASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsG |
| 125 | +# AQQBgjcVAgQWBBQ/0jsn2LS8aZiDw0omqt9+KWpj3DAdBgNVHQ4EFgQUicLX4r2C |
| 126 | +# Kn0Zf5NYut8n7bkyhf4wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDgYDVR0P |
| 127 | +# AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUdpW6phL2RQNF |
| 128 | +# 7AZBgQV4tgr7OE0wMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovL3BraS9jZXJ0ZGF0 |
| 129 | +# YS9aZXJvREMwMS5jcmwwPAYIKwYBBQUHAQEEMDAuMCwGCCsGAQUFBzAChiBodHRw |
| 130 | +# Oi8vcGtpL2NlcnRkYXRhL1plcm9EQzAxLmNydDANBgkqhkiG9w0BAQsFAAOCAQEA |
| 131 | +# tyX7aHk8vUM2WTQKINtrHKJJi29HaxhPaHrNZ0c32H70YZoFFaryM0GMowEaDbj0 |
| 132 | +# a3ShBuQWfW7bD7Z4DmNc5Q6cp7JeDKSZHwe5JWFGrl7DlSFSab/+a0GQgtG05dXW |
| 133 | +# YVQsrwgfTDRXkmpLQxvSxAbxKiGrnuS+kaYmzRVDYWSZHwHFNgxeZ/La9/8FdCir |
| 134 | +# MXdJEAGzG+9TwO9JvJSyoGTzu7n93IQp6QteRlaYVemd5/fYqBhtskk1zDiv9edk |
| 135 | +# mHHpRWf9Xo94ZPEy7BqmDuixm4LdmmzIcFWqGGMo51hvzz0EaE8K5HuNvNaUB/hq |
| 136 | +# MTOIB5145K8bFOoKHO4LkTCCBc8wggS3oAMCAQICE1gAAAH5oOvjAv3166MAAQAA |
| 137 | +# AfkwDQYJKoZIhvcNAQELBQAwPTETMBEGCgmSJomT8ixkARkWA0xBQjEUMBIGCgmS |
| 138 | +# JomT8ixkARkWBFpFUk8xEDAOBgNVBAMTB1plcm9TQ0EwHhcNMTcwOTIwMjE0MTIy |
| 139 | +# WhcNMTkwOTIwMjExMzU4WjBpMQswCQYDVQQGEwJVUzELMAkGA1UECBMCUEExFTAT |
| 140 | +# BgNVBAcTDFBoaWxhZGVscGhpYTEVMBMGA1UEChMMRGlNYWdnaW8gSW5jMQswCQYD |
| 141 | +# VQQLEwJJVDESMBAGA1UEAxMJWmVyb0NvZGUyMIIBIjANBgkqhkiG9w0BAQEFAAOC |
| 142 | +# AQ8AMIIBCgKCAQEAxX0+4yas6xfiaNVVVZJB2aRK+gS3iEMLx8wMF3kLJYLJyR+l |
| 143 | +# rcGF/x3gMxcvkKJQouLuChjh2+i7Ra1aO37ch3X3KDMZIoWrSzbbvqdBlwax7Gsm |
| 144 | +# BdLH9HZimSMCVgux0IfkClvnOlrc7Wpv1jqgvseRku5YKnNm1JD+91JDp/hBWRxR |
| 145 | +# 3Qg2OR667FJd1Q/5FWwAdrzoQbFUuvAyeVl7TNW0n1XUHRgq9+ZYawb+fxl1ruTj |
| 146 | +# 3MoktaLVzFKWqeHPKvgUTTnXvEbLh9RzX1eApZfTJmnUjBcl1tCQbSzLYkfJlJO6 |
| 147 | +# eRUHZwojUK+TkidfklU2SpgvyJm2DhCtssFWiQIDAQABo4ICmjCCApYwDgYDVR0P |
| 148 | +# AQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBS5d2bhatXq |
| 149 | +# eUDFo9KltQWHthbPKzAfBgNVHSMEGDAWgBSJwtfivYIqfRl/k1i63yftuTKF/jCB |
| 150 | +# 6QYDVR0fBIHhMIHeMIHboIHYoIHVhoGubGRhcDovLy9DTj1aZXJvU0NBKDEpLENO |
| 151 | +# PVplcm9TQ0EsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNl |
| 152 | +# cnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9emVybyxEQz1sYWI/Y2VydGlmaWNh |
| 153 | +# dGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlv |
| 154 | +# blBvaW50hiJodHRwOi8vcGtpL2NlcnRkYXRhL1plcm9TQ0EoMSkuY3JsMIHmBggr |
| 155 | +# BgEFBQcBAQSB2TCB1jCBowYIKwYBBQUHMAKGgZZsZGFwOi8vL0NOPVplcm9TQ0Es |
| 156 | +# Q049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENO |
| 157 | +# PUNvbmZpZ3VyYXRpb24sREM9emVybyxEQz1sYWI/Y0FDZXJ0aWZpY2F0ZT9iYXNl |
| 158 | +# P29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwLgYIKwYBBQUHMAKG |
| 159 | +# Imh0dHA6Ly9wa2kvY2VydGRhdGEvWmVyb1NDQSgxKS5jcnQwPQYJKwYBBAGCNxUH |
| 160 | +# BDAwLgYmKwYBBAGCNxUIg7j0P4Sb8nmD8Y84g7C3MobRzXiBJ6HzzB+P2VUCAWQC |
| 161 | +# AQUwGwYJKwYBBAGCNxUKBA4wDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOC |
| 162 | +# AQEAszRRF+YTPhd9UbkJZy/pZQIqTjpXLpbhxWzs1ECTwtIbJPiI4dhAVAjrzkGj |
| 163 | +# DyXYWmpnNsyk19qE82AX75G9FLESfHbtesUXnrhbnsov4/D/qmXk/1KD9CE0lQHF |
| 164 | +# Lu2DvOsdf2mp2pjdeBgKMRuy4cZ0VCc/myO7uy7dq0CvVdXRsQC6Fqtr7yob9NbE |
| 165 | +# OdUYDBAGrt5ZAkw5YeL8H9E3JLGXtE7ir3ksT6Ki1mont2epJfHkO5JkmOI6XVtg |
| 166 | +# anuOGbo62885BOiXLu5+H2Fg+8ueTP40zFhfLh3e3Kj6Lm/NdovqqTBAsk04tFW9 |
| 167 | +# Hp4gWfVc0gTDwok3rHOrfIY35TGCAfUwggHxAgEBMFQwPTETMBEGCgmSJomT8ixk |
| 168 | +# ARkWA0xBQjEUMBIGCgmSJomT8ixkARkWBFpFUk8xEDAOBgNVBAMTB1plcm9TQ0EC |
| 169 | +# E1gAAAH5oOvjAv3166MAAQAAAfkwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwx |
| 170 | +# CjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGC |
| 171 | +# NwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFCUWn8gAPBTWrgC3 |
| 172 | +# qd7PySPrG31HMA0GCSqGSIb3DQEBAQUABIIBAGA7eE5j189oxjfO0fnNQptRz8gs |
| 173 | +# p6lO9LwXB5dt5ZKAAFV+hq0wCjqobTgcXlzYjyX2KBQFFH4Dw/SM/ZqYzzL1iqIl |
| 174 | +# l4dasHRj/WGUmIVU8XN+Lim5WVej5jn3PtpmIXmunKieVGMdWPxjD6DO1F32EQWX |
| 175 | +# 3axaADU1MgZ096s42HZWp9VTl5FKiKsnj2CblVZ4iEFXThqVePJI/rWaITqmMs0n |
| 176 | +# 8Wv7eHVNEt7FTy4+AXK69zer9tThrzJ2H+HHVxIumTSR5RHZ68pU5aDMooAMMCva |
| 177 | +# c5+D1pCa58RV0pGBeKes522qJ8njxoyeVVAXDH1xmmahiEC/ImJuCsQP/pw= |
| 178 | +# SIG # End signature block |
0 commit comments