Link to home
Start Free TrialLog in
Avatar of samiam41
samiam41Flag for United States of America

asked on

Uninstall KB via Powershell on PC's in a list

Hey Experts.  I need to uninstall Windows patches (5005033, 5103, 5031) while I work to resolve the printer installation process here.  To expedite the uninstall process, I've identified the KB's responsible and which PC's are affected.  However the Powershell script I'm attempting to build is not coming along as smoothly as I thought and due to time constraints, I need your help.


So far, I've been testing this:

$myComputers = Get-Content
"c:\scripts\mycomputers.txt"
foreach ($computer in $myComputers) {
 Uninstall-HotFix -ComputerName $computer
-HotfixID KB123456}

Open in new window

But I wanted to at least output whether the update was successfully uninstalled.  Any help on how to modify this to output the results?

Avatar of Andrew Porter
Andrew Porter
Flag of United States of America image

Get-WmiObject -query “Select HotFixID from Win32_QuickFixengineering” | select HotFixID | where {$_ -match 'KB2506143' }

Open in new window

Avatar of samiam41

ASKER

Thanks Andrew however I don't know how that outputs the results or where to put it in the script.  My apologies for any confusion as to my PS level as noob is more accurate.
Let me go about this a little differently.
Since oBdA was able to perfect the way in which PC's are sorted based on which KB was detected, I just need the script to pull the list of pc's from KB_Log_1.txt and uninstall the KB set in the script.  Output results though?

$KBNumber = 5005103
Get-Content 'C:\tools\KB\KB5005103.txt' | ForEach-Object {
   $computer = $_
   Write-Host "Processing $($computer) ..."
   If (Test-Connection -ComputerName $computer -Count 1 -Quiet) {
        $RemovalCommand = "wusa.exe /uninstall /kb:$KBNumber /quiet /log /norestart";
   Write-Host ("Removing update with command: " + $RemovalCommand);
   Invoke-Expression -Command $RemovalCommand;
   Write-Output "$kbnumber uninstalled on $computer" | out-file -append "c:\tools\kb\Logs\5103_Uninstalled.txt"
while (@(Get-Process wusa -ErrorAction SilentlyContinue).Count -ne 0)
    {
        Start-Sleep 1
        Write-Host "Waiting for update removal to finish ..."
    }
}
}

Open in new window

Avatar of oBdA
oBdA

That script would only ever uninstall on the computer you're running it on ...
This requires Remote PS on the clients (and is untested).
$KBNumber = 'KB5005103'
$LogFile = "C:\tools\kb\Logs\Uninst_$($KBNumber).csv"
$WusaLog = "C:\Windows\Temp\Uninst_$($KBNumber).evt"	# Locally on the remote machine!

Get-Content "C:\tools\KB\$($KBNumber).txt" | ForEach-Object {
	$computer = $_
	Write-Host "Processing $($computer) ..."
	If (Test-Connection -ComputerName $computer -Count 1 -Quiet) {
		Try {
			Invoke-Command -ErrorAction Stop -ComputerName $computer -ArgumentList $KBNumber, $WusaLog -ScriptBlock {
			Param($KBNumber, $WusaLog)
				$kbid = $KBNumber -replace '\D'
				& wusa.exe /uninstall /kb:$($kbid) /quiet /norestart /log:"`"$($WusaLog)`"" | Out-Null
				Switch ($LastExitCode) {
					0		{}
					3010	{}
					default	{Throw "wusa.exe finished with ExitCode $($_)!"}
				}
			}
			'' | Select-Object -Property @{n='ComputerName'; e={$computer}},  @{n='Result'; e={'OK'}}
		} Catch {
			$_ | Select-Object -Property @{n='ComputerName'; e={$computer}},  @{n='Result'; e={$_.Exception.Message}}
		}
	} Else {
		'' | Select-Object -Property @{n='ComputerName'; e={$computer}},  @{n='Result'; e={'Offline'}}
	}
} | Export-Csv -NoTypeInformation -Path $LogFile

Open in new window

Well that would explain a lot.

Testing your masterwork now, updates shortly.
 wusa.exe finished with ExitCode 87!

That's the code showing up in the spreadsheet.  I'm not sure what it means.

Restarting the test pc after the script ran and gave that error.

**Did not uninstall that patch.  

I'm at a loss as to why that patch can't be uninstalled through Powershell.  They're closing our office for the day and I'm clearing the building.  Won't be back until Tuesday.  I apologize for the gap but greatly appreciate your time and assistance.
Seems like MS removed the /quiet switch in combination with /kb.
This is untested as well, so run it on some test machines first:
$KBNumber = 'KB5005103'
$LogFile = "C:\tools\kb\Logs\Uninst_$($KBNumber).csv"

Get-Content "C:\tools\KB\$($KBNumber).txt" | ForEach-Object {
	$computer = $_
	Write-Host "Processing $($computer) ..."
	If (Test-Connection -ComputerName $computer -Count 1 -Quiet) {
		Try {
			Invoke-Command -ErrorAction Stop -ComputerName $computer -ArgumentList $KBNumber -ScriptBlock {
			Param($KBNumber)
				$package = Get-WindowsPackage -Online -PackageName "Package_for_$($_.HotFixId)*"
				If ($package) {
					$package | Remove-WindowsPackage -Online -ErrorAction Stop
				} Else {
					Throw "WindowsPackage for $($KBNumber) not found!"
				}
			}
			'' | Select-Object -Property @{n='ComputerName'; e={$computer}},  @{n='Result'; e={'OK'}}
		} Catch {
			$_ | Select-Object -Property @{n='ComputerName'; e={$computer}},  @{n='Result'; e={$_.Exception.Message}}
		}
	} Else {
		'' | Select-Object -Property @{n='ComputerName'; e={$computer}},  @{n='Result'; e={'Offline'}}
	}
} | Export-Csv -NoTypeInformation -Path $LogFile

Open in new window

Great script and shows that the patch was uninstalled before prompting to restart the pc.  I checked if the patch was there after the pc restarted and it is.  Not sure why I get a false positive.  Log file shows:
 
PSComputerNameRunspaceIdPSShowComputerNamePathOnlineWinPathSysDrivePathRestartNeededLogPathScratchDirectoryLogLevel
PC3b561f92-d174-4739-9fe6-90410c1beefdTRUE
TRUE

FALSEC:\Windows\Logs\DISM\dism.log
WarningsInfo
PC3b561f92-d174-4739-9fe6-90410c1beefdTRUE
TRUE

FALSEC:\Windows\Logs\DISM\dism.log
WarningsInfo
PC3b561f92-d174-4739-9fe6-90410c1beefdTRUE
TRUE

TRUEC:\Windows\Logs\DISM\dism.log
WarningsInfo
PC3b561f92-d174-4739-9fe6-90410c1beefdTRUE
TRUE

TRUEC:\Windows\Logs\DISM\dism.log
WarningsInfo

ASKER CERTIFIED SOLUTION
Avatar of oBdA
oBdA

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks oBdA!!  I briefly checked it but no longer have the time to thoroughly vet it.  I appreciate your diligence, time and solution with the question.