Skip to content

Commit 258cd70

Browse files
author
pldmgg
committed
Initial commit for Uninstall-MSU function
1 parent 86d34cc commit 258cd70

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

MyFunctions/Uninstall-MSU.ps1

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
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

Comments
 (0)