Need some help in fixing PowerShell to export Windows Update to. CSV file ?

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,

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.

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."