Last active
June 28, 2017 18:51
-
-
Save markekraus/47c78dbbb106cc27558c435446aafd50 to your computer and use it in GitHub Desktop.
Patch AD Computers for NotPetya. Supports multiple runs to skip previously patched machines and provides detailed logging objects.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Modules PoshRSJob, ActiveDirectory | |
# create this file as read-Only before running script | |
$SourceFile = "C:\perfc" | |
$ServerFilter = {enabled -eq $True -and DnsHostName -like "*" -and operatingSystem -like "*windows*"} | |
$SearchBase = "dc=adatum,dc=com" | |
$LogFile = "C:\NotPetyaPatch.xml" | |
$Throttle = 40 | |
$StartDate = Get-Date | |
$Results = [System.Collections.ArrayList]::new() | |
$Vaccinated = [System.Collections.ArrayList]::new() | |
$PreviousResults = Import-Clixml -Path $LogFile -ErrorAction SilentlyContinue | |
Foreach($PreviousResult in $PreviousResults){ | |
if($PreviousResult.Vaccinated -eq $true){ | |
$null = $Results.Add($PreviousResult) | |
$null = $Vaccinated.Add($PreviousResult.Server.SID.Value) | |
} | |
} | |
$Results | Select-Object ComputerName, Vaccinated, Date | Format-Table | |
$Servers = Get-ADComputer -filter $ServerFilter -SearchBase $SearchBase | Where-Object {$_.SID.Value -notin $Vaccinated} | |
$Servers | Start-RSJob -Name {$_.DnsHostName} -Throttle $Throttle -ScriptBlock { | |
$Server = $_ | |
$ComputerName = $Server.DnsHostName | |
$SourceFile = $using:SourceFile | |
$AdminShare = '\\{0}\C$' -f $ComputerName | |
$DestinationFiles = @( | |
Join-Path -Path $AdminShare -ChildPath '\Windows\perfc' | |
Join-Path -Path $AdminShare -ChildPath '\Windows\perfc.dat' | |
Join-Path -Path $AdminShare -ChildPath '\Windows\perfc.dll' | |
) | |
$Result = [PSCustomObject]@{ | |
Server = $Server | |
ComputerName = $ComputerName | |
PathAvailable = $false | |
Vaccinated = "Unknown" | |
Errors = [System.Collections.ArrayList]::new() | |
CopyResults = [System.Collections.ArrayList]::new() | |
Date = Get-Date | |
} | |
if (-not (Test-Path -Path $AdminShare)) { | |
return $Result | |
} | |
$Result.PathAvailable = $True | |
foreach($DestinationFile in $DestinationFiles){ | |
$DestinationResult = [PSCustomObject]@{ | |
DestinationFile = $DestinationFile | |
FileAlreadyExists = $false | |
CopyAttempted = $false | |
CopySuccessful = $false | |
} | |
if (Test-Path -Path $DestinationFile) { | |
$DestinationResult.FileAlreadyExists = $true | |
$DestinationResult.CopySuccessful = $true | |
$null = $Result.CopyResults.Add($DestinationResult) | |
continue | |
} | |
try { | |
$DestinationResult.CopyAttempted = $True | |
$Null = Copy-Item -Path $SourceFile -destination $DestinationFile -ErrorAction Stop | |
} | |
catch { | |
$null = $Result.Errors.Add($_) | |
$null = $Result.CopyResults.Add($DestinationResult) | |
continue | |
} | |
if (Test-Path -Path $DestinationFile) { | |
$DestinationResult.CopySuccessful = $true | |
} | |
$null = $Result.CopyResults.Add($DestinationResult) | |
} | |
if($false -in $Result.CopyResults.CopySuccessful){ | |
$Result.Vaccinated = $false | |
} | |
else{ | |
$Result.Vaccinated = $true | |
} | |
return $Result | |
} | Wait-RSJob | Receive-RSJob | ForEach-Object { | |
$null = $Results.Add($_) | |
$_ | Select-Object ComputerName, Vaccinated | |
} | Format-Table | |
$VaccinatedTotal = $Results.Where({$_.vaccinated -eq $True}).Count | |
$VaccinatedThisRun = $VaccinatedTotal - $Vaccinated.Count | |
$EndDate = Get-Date | |
" " | |
"Results" | |
"---------------------------" | |
"Previously Vaccinated: {0}" -f $Vaccinated.Count | |
"Vaccinated This Run: {0}" -f $VaccinatedThisRun | |
"Vaccinated Total: {0}" -f $VaccinatedTotal | |
"Failed: {0}" -f $Results.Where({$_.vaccinated -eq $false}).Count | |
"Unknown: {0}" -f $Results.Where({$_.vaccinated -like "Unknown"}).Count | |
"Start Date: {0}" -f $StartDate | |
"End Date: {0}" -f $EndDate | |
"Run time: {0}" -f ($EndDate - $StartDate) | |
Get-RSJob | Remove-RSJob -Force | |
$Results | Export-Clixml -Path $LogFile |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment