Hi All,
I need to get the list of the server last windows update patch from multiple different OU and then export it as in CSV file with the below column:
ServerName, Last Time Update Installed, KB Number, KB Update Name
This is the script for multiple OU processing, but somehow the result is still blank.CSV file?
$CsvFile = 'C:\Result.csv'
$key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install'
$keytype = [Microsoft.Win32.RegistryHive]::LocalMachine
$OUList = @(
“OU=TEST Servers,OU=MyDomain Testing,DC=MyDomain,DC=com”
“OU=PROD Servers,OU=Servers,OU=MyDomain,DC=MyDomain,DC=com”
“OU=PROD Servers,OU=Servers,OU=New Company,DC=MyDomain,DC=com”
)
$OUList | ForEach-Object {
$OU = $_
$Computers = Get-ADComputer -Filter {Enabled -eq $True -and OperatingSystem -like “Server”} -SearchBase $OU |
Select-Object -ExpandProperty DNSHostName |
ForEach-Object {
If (Test-Connection $_ -Count 1 -Quiet) {
$_
}
Else {
Write-Host “Cannot reach $($_)” -ForegroundColor Red
}
}
ForEach ($computer in $Computers) {
Try {
$remoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype, $computer)
$regKey = $remoteBase.OpenSubKey($key)
$keyValue = $regkey.GetValue(‘LastSuccessTime’)
Write-Host ‘’
Write-Host “$($computer): last time updates were installed was $($keyValue)”
}
Catch {
$ | Write-Error
}
Finally {
If ($regKey) {$regKey.Close()}
}
}
} | Export-Csv -Path $Csvfile -NoTypeInformation
I’d like to know if the below result is possible just like running
Get-HotFix locally on each server:
ServerName, Last Time Update Installed, KB Number, KB Update Name, InstalledBy
PRODSQL01-VM, 31/12/2018 02:46:55, KB4462930, Cumulative Update, NT AUTHORITY\SYSTEM
PRODSQL02-VM, 18/12/2018 12:00:00 AM, KB4471324, Security Update, DOMAIN\SVC_SCCM
PRODDC01-VM, 16/1/2019 02:16:31, KB4343669, Cumulative Update, DOMAIN\SVC_SCCM
PRODDC02-VM, 13/1/2018 03:00:00 AM, KB4457146, Security Update, DOMAIN\Admin-Staff1
Any help would be greatly appreciated.
Thanks,
bkindle
2
Using the [pre]Invoke-Command[/pre]cmdlet, you could fashion your code to loop through every computer in the target OU.
This is just a example of how I accomplished a similar project a few weeks back:
$servers = Get-Content -Path '.\hosts.txt'
Invoke-Command -ComputerName $servers -ScriptBlock {
Get-HotFix | Select-Object -Property PSComputerName, Description, HotFixID, InstalledOn
}
You can pipe the above code to whatever type of output you are looking for.
I am curious as to why you are trying to pull this info from the registry using .NET methods though.
Olaf
3
It’s even easier than that. Get-Hotfix supports the parameter -ComputerName. So you actually only need something like this:
$CsvFile = ‘C:\Result.csv’
$OUList = @(
‘OU=TEST Servers,OU=MyDomain Testing,DC=MyDomain,DC=com’
‘OU=PROD Servers,OU=Servers,OU=MyDomain,DC=MyDomain,DC=com’
‘OU=PROD Servers,OU=Servers,OU=New Company,DC=MyDomain,DC=com’
)
$Result = ForEach ($OU in $OUList) {
Get-ADComputer -Filter {Enabled -eq $True -and OperatingSystem -like “Server”} -SearchBase $OU |
ForEach-Object {
If (Test-Connection $.Name -Count 1 -Quiet) {
Get-HotFix -ComputerName $.Name | Select-Object -Property PSComputerName, Description, HotFixID, InstalledOn, InstalledBy
}
}
}
$Result |
Export-Csv -Path $Csvfile -NoTypeInformation
Thanks all for the suggestion.
I need the last date of the patch applied, hence I put the key $keyValue = $regkey.GetValue(‘LastSuccessTime’).
So I can now change that into:
Get-HotFix -ComputerName $_.Name | Sort-Object InstalledOn | Select-Object -Property PSComputerName, Description, HotFixID, InstalledOn, InstalledBy -Last 1
Would that be correct?
What would be the difference with the WMI method?
Get-WmiObject -Class "Win32_QuickFixEngineering" -ComputerName $_.Name-ErrorAction Stop |
Select-Object -Property `
@{Name="ComputerName"; Expression={$Server}},
"Description",
"HotfixID",
@{Name="InstalledOn"; Expression={([DateTime]($_.InstalledOn)).ToLocalTime()}},
"Error"
"OK."