Get the last Windows Update install date using PowerShell

26,757

Solution 1

Does Get-HotFix meet your needs?

Get-HotFix -ComputerName $_.Name | Measure-Object InstalledOn -Maximum

Your performance issues could be coming from Get-ADComputer. I'd do some troubleshooting to see which piece is causing you problems.

Solution 2

Tim Ferrill already provided you the answer but for the record you could have done something like this

$ScriptBlock = {
    $hash=@{}
    $Session = New-Object -ComObject Microsoft.Update.Session
    $Searcher = $Session.CreateUpdateSearcher()
    $hash[$env:Computername] = $Searcher.QueryHistory(1,1) | select -ExpandProperty Date
    $hash
}

Invoke-Command -ComputerName $serverlist -ScriptBlock $ScriptBlock

This would get you something like

Name                    Value
----                    -----
Server1                 5/16/2014 2:11:42 PM
Server2                 4/14/2014 1:55:03 PM
Server3                 5/6/2014 5:36:51 PM
Share:
26,757
Keltari
Author by

Keltari

Updated on July 15, 2022

Comments

  • Keltari
    Keltari almost 2 years

    I am trying to write a PowerShell script that will query all the servers in Active Directory and see the last date a Windows Update was applied.

    I was having some trouble, so just to get it done, I created two scripts, one in Powershell to get the servers and the other in VBScript to query the last date. I found a this Powershell module that allows me to query the last install date, but it is extremely slow, especially on remote servers.

    Here is the PS code:

    Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' -Properties * |
    Select-Object Name | Sort-Object Name |
    ForEach-Object {
        Get-WUHistory -ComputerName $_.Name | Sort-Object Date,ComputerName -Descending |
        Select-Object -First 1
    }
    

    Its so slow, its practically unusable.

    I have some VBScript which I cobbled together that is much faster. See below:

    On Error Resume Next
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set file = fso.OpenTextFile ("servers.csv", 1)
    server = ""
    
    Do Until file.AtEndOfStream
      line = file.Readline
      server = line
      'wscript.echo server
      Set objSession = CreateObject("Microsoft.Update.Session", server)
      If Err.Number <> 0 Then
        'WScript.Echo server & " Error: " & Err.Number & " Error (Hex): " & Hex(Err.Number) & " Source: " &  Err.Source & " Description: " &  Err.Description
        WScript.Echo server & " Communications Error"
        Err.Clear
      Else
          Set objSearcher = objSession.CreateUpdateSearcher
          Set colHistory = objSearcher.QueryHistory(1, 1)
          For Each objEntry in colHistory
            Wscript.Echo server & " " & objEntry.Date
          Next
      End If
    Loop
    
    file.Close
    

    Is there an easy way to get the speed of the VBScript into the Powershell code?


    Here is the working Powershell code (modified again) if anyone is interested:

    $ErrorActionPreference= 'silentlycontinue'
    Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' -Properties * | Select-Object Name |
    ForEach-Object {
        If (Test-Connection $_.Name -Count 1){
            Get-HotFix -ComputerName $_.Name | Sort-Object InstalledOn -Descending | Select-Object -First 1 
        }
        else {
            Write-host $_.Name " Connection Error"
        }
    } |
    Sort-Object InstalledOn
    
  • Keltari
    Keltari about 10 years
    If you mean Get-ADComputer, then no thats pretty quick. The slowness is definitely from Get-WUHistory. Im trying get-hotfix now.
  • Tim Ferrill
    Tim Ferrill about 10 years
    Yeah, that. Where'd I put that coffee?
  • Keltari
    Keltari about 10 years
    This works at a reasonable speed. Putting my amended script in the question.
  • Keltari
    Keltari about 10 years
    Hm. Ill check this out
  • Admin
    Admin over 8 years
    Get-Hotfix does require Powershell 3.0 or greater, but a fair enough trade-off and as a bonus meets the requirement for many scenarios where a course-grained one-liner is enough.