List HotFixes using PowerCLI
List HotFixes using PowerCLI – Have you ever wondered how can i get the current patch level for all your windows vm’s in my VMware environment, well the first thought which would come into your mind is to login to all those 100’s of vm’s and manually get the patch level or if you have thought ahead you would go and purchase an enterprise patch management tool ( Which is the preferred way ).
But what if you don’t have the budget or you need this info really fast!!, That’s when powercli and powershell come to the rescue 🙂
Here’s a script which can help you get the job done, the first part of the script we would be extracting the list of current hotfixes across all windows vm’s in your vsphere environment and in the second part we would get the list of missing patches!
So Here we go!!
Below script would get the list of all current patches in your vSphere environment.
The script assumes that you have a VISession already established to your vcenter server. Or the best way is to code it in your script itself by passing the $vcenterserver and $credential as parameters.
Add-pssnapin VMware.VimAutomation.Core Connect-VIServer $vcenterserver -Credential (Get-Credential)
So once we are connected to the vcenter server, lets start building our script, i have broken down the script with detailed explanation.
First lets get the credential to authenticate into the windows vm’s ( Assuming you have a service account which has the required privileges and is having sufficient rights to extract the info )
$admcred = Get-Credential
Next comes the real fun, creating VI properties for the properties you want to extract, this can save you lots of time where in you would try to create a custom property using powershell {l=’ineedthis’;e={$_.stuff}}
We will create VI properties for GuestFamily, GuestOSType, GuestHostName and GuestHostIP, this would allow us to extract these properties easily with select statement without complex custom properties.
New-VIProperty -Name GuestFamily -ObjectType VirtualMachine -ValueFromExtensionProperty 'guest.guestfamily' -Force New-VIProperty -Name GuestOSType -ObjectType VirtualMachine -ValueFromExtensionProperty 'guest.guestfullname' -Force New-VIProperty -Name GuestHostName -ObjectType VirtualMachine -ValueFromExtensionProperty 'guest.hostname' -Force New-VIProperty -Name GuestHostIP -ObjectType VirtualMachine -ValueFromExtensionProperty 'guest.IpAddress' -Force
Next Lets get the above created property details for all windows VM’s across our vcenter environment
$allwinvms = Get-VM | select name,GuestHostName,GuestHostIP,guestfamily,guestostype | ?{$_.guestfamily -match "windowsGuest"} | Sort-Object guestostype
Next Lets get into the juice of the script, create an Array which would save all the properties. After that we would iterate across all windows VM’s and get the hotfix installed and its associated properties, also you can see that i am using a try catch statement to filter out the hosts which are not reachable ( you can also out these hostnames to a notepad file (out-file c:\failedvms.txt)).
I also used the write-progress cmdlet to track the current progress of the script with which it would show the admin a transparent UI on whats going on and which VMs are being queried for patches.
$array = @() $allwinvms | foreach-object -begin {$i=0;$out=""} ` -process { $ghn = $_.GuestHostName try { $i = $i+1; write-progress -id 1 -activity "Querying VMs" -status "Looking up Hotfixes on $($_.guesthostname) $i% Complete: " -percentcomplete ($i/$allwinvms.count*100) Write-Host "`nExtracting list of Hotfixes for "$_.guesthostname" " -ForegroundColor Yellow -BackgroundColor Black $array += Get-HotFix -ComputerName $ghn -Credential $admcred | where-object {$_.hotfixid -ne "file 1"} | Select PSComputerName,HotFixID,InstalledBy, @{l="InstalledOn";e={[DateTime]$_.psbase.properties["installedon"].value}} } catch { Write-Host "`n $ghn is not reachable" -ForegroundColor Yellow -BackgroundColor Red } }
Once the script completes all your hotfix information would be residing in $array variable which you can now easily export to a CSV 😉
Ok so now that’s done, lets head on to our second use case – Extract the list of missing patches across your windows servers, for this we would using the MBSA (Microsoft Baseline Security Analyzer) tool from microsoft, a nice little tool which queries a computer against the security patches which Microsoft recommends to install and gives us a report on the missing patches.
MBSA Tool Output
The current script assumes that you have installed the 64 bit version of the MBSA tool.
So lets explore the script, most parts of the script remain the same including creating the VI properties, let dig in right to the core!
We would start the similar way – extract all the details of windows vm’s in the vcenter environment, next i would extract the username and password from the credential object and use it to run the mbsa tool against the VM’s, also note that i am using two progress bars here, one which gives a live view on how much time elapsed from the time the script started and another one which shows the current VM being queried aganist by MBSA. Once the MBSA Tool generates the reports we would convert them into an XML format and extract the required information about missing patches and add them into an array.Also note the usage of a try-catch statement which will catch the hosts which are not reachable.
$allwinvms = Get-VM | select name,GuestHostName,GuestHostIP,guestfamily,guestostype | ?{$_.guestfamily -match "windowsGuest"} | Sort-Object guestostype $ExeFilePath = "C:\Program Files\Microsoft Baseline Security Analyzer 2\mbsacli.exe" if (!(Test-Path $ExeFilePath)) { throw "$ExeFilePath not found" } $arraymbsa = @() $allwinvms | foreach-object -begin {$i=0;$out="";$elapsedTime = [system.diagnostics.stopwatch]::StartNew()} ` -process { $ghn = $_.GuestHostName $vmcount = $allwinvms.count write-progress -activity "Working..." -status "$([string]::Format("Time Elapsed: {0:d2}:{1:d2}:{2:d2}", $elapsedTime.Elapsed.hours, $elapsedTime.Elapsed.minutes, $elapsedTime.Elapsed.seconds))" try { $i = $i+1; $username = $admcred.GetNetworkCredential().username $password = $admcred.GetNetworkCredential().password write-progress -id 1 -activity "Querying VMs $i of $vmcount " -status "Executing MBSA on $($_.guesthostname) $i VM In Progress: " -percentcomplete ($i/$allwinvms.count*100) Write-Host "`nExtracting list of Missing Hotfixes for "$_.guesthostname" " -ForegroundColor Yellow -BackgroundColor Black #Get-HotFix -ComputerName $ghn -Credential $admcred | select -First 1 Test-Connection -ComputerName $ghn -Count 2 -Quiet -ErrorAction Stop | Out-Null & $ExeFilePath /target $ghn /u $username /p $password /wi /nvc /o %C% 2>&1> $null [xml]$ScanResults = Get-Content "$($Env:USERPROFILE)\SecurityScans\$($ghn.Split('.')[0]).mbsa" -ErrorAction SilentlyContinue $UpdateSeverityLabels = @{ '0' = 'Other' '1' = 'Low' '2' = 'Moderate' '3' = 'Important' '4' = 'Critical' } $MissingUpdates = $ScanResults.SelectNodes("//Check[@Name='Windows Security Updates']/Detail/UpdateData[@IsInstalled='false']") $MissingUpdates = $MissingUpdates | select @{l='HostName';e={$ghn}},KBID,IsInstalled,Severity,RestartRequired,Title $arraymbsa += $MissingUpdates } catch { Write-Host "`n $ghn is not reachable" -ForegroundColor Yellow -BackgroundColor Red $ghn | Out-File "C:\hostsnotreachable.txt" -Append } }
Once the script completes all your missing hotfix information would be residing in $arraymbsa variable which you can now easily export to a CSV 😉 ($arraymbsa | Export-Csv c:\hfix.csv -NoTypeInformation)
List HotFixes using PowerCLI
I hope you enjoyed this blogpost on “List HotFixes using PowerCLI” and found this information useful 🙂
Hi Vinith,
Nice article! I like how you have been using the MBSA. It is a nice approch. I have also developed an identical solution using the information from the SCCM client. The main advantage of this approch, is that we can see which patches are missing from the ones that have actually ‘really’ been deployed to that machine. You can have a look at it here
http://powershelldistrict.com/missing-software-updates-powershell/
Thanks stephane, yes let me have a look