Script for windws server validation post patching

Avinash Kumar 1 Reputation point
2022-11-21T04:38:09.597+00:00

Hi All,

I have a requirement to validate the windows servers post patching. it is basically customized requirement to verify the following components post patching (only windows servers)

1)Last windows patch installation date and status of patch (Filed, installed ..etc)
2)Server pending reboot because of patching
3)Server reboot timing
4)All automatic service status.

It would be great help if anyone can share their idea. Close to this requirement will be also fine.

Windows Server
Windows Server
A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.
12,121 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. MotoX80 31,571 Reputation points
    2022-11-22T13:59:22+00:00

    Years ago I built a status report tool using VB script and HTA's. (Powershell had not been born yet.) We enhanced/tweaked it over time and ultimately build an HTML report that was emailed to the entire team.

    I hacked together some scripts that I had laying around and mostly replicated that in Powershell. This assumes that you have an Active Directory environment and the account running the script has admin access to the servers. It requires that you have set up WinRM on each machine and Invoke-Command works. (Winrm quickconfig)

    This should give you a starting point that you can build on to customize for your environment. Adding in code to report on disk space usage would be a good next step.

    # ShowStatus.ps1 courtesy of MotoX80.   
    $servers = @("win10home","test10")       # or use get-content to read a list of names from a file.   
    $Results = @()  
    Get-Job | Remove-job               # clear out jobs for when testing in ISE   
    $script =   
    {  
        # This code runs on each server to analyze it's health.   
        "<tr bgcolor=lightgreen><td>--------  {0}  ----------</td></tr>" -f $env:COMPUTERNAME   
        "<tr><td>Last boot: {0}</td></tr>" -f (Get-CimInstance win32_operatingsystem).LastBootUpTime   
        "<tr><td>Services not running.<pre>"  
        get-service | where-object -property Status -eq  Stopped | where-object -property StartType -eq  Automatic | Format-Table -Property Name, DisplayName  
        "</pre></td></tr>"  
      
        $wur = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"  
        if ($wur) {  
            "<tr><td>Windows update requires a reboot.</td></tr>"           
        } else {  
            "<tr><td>Windows update does not require a reboot.</td></tr>"  
        }  
      
        # This does not detect optional updates.   
        $objSession = new-object -comobject "Microsoft.Update.Session"  
        $objSearcher = $objSession.CreateUpdateSearcher()  
        $objResults = $objSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0 and Type='Software'")    
        $colUpdates = $objResults.Updates  
        "<tr><td>There are {0} updates that need installed.</td></tr>" -f $colUpdates.Count  
    }  
      
    # Launch the script for all machines using PS's job functionality  
    $Results += '<html><body><h3>Server Status Report</h3><table  style="font-family:Verdana">'  
    foreach ($computer in $servers) {  
        While($true) {  
            if ((Get-Job -State 'Running').Count -ge 5) {     # number of concurrent jobs to run  
                "Max concurrent job limit reached."    
                Start-Sleep -Seconds 10                       # don't overload this machine   
            } else {  
                break  
            }  
        }  
        Invoke-Command -ComputerName $computer  -ScriptBlock $script -AsJob   
    }     
       
    # Now wait until all jobs have stopped running.  
    $limit = 0  
    While($true) {  
        if ((Get-Job -State 'Running').Count -ne 0) {  
            Start-Sleep -Seconds 30                     # wait a bit   
            $limit++    
            if ($limit -gt 10) {                        # they should finish within 5 minutes   
                Get-Job -State 'Running' | foreach {  
                     $Results += "<tr><td bgcolor=red>{0} appears to be hung.." -f $_.Location  
                }  
                "Time limit exceeded."  
                break  
            }  
        } else {  
            break           # exit the infinite while statement because no jobs are running.    
        }  
    }  
      
    # Read the output from all jobs and add that to the report.   
    $Alljobs = Get-Job  
    foreach ($Job in $Alljobs) {  
        if ($job.State -eq "Failed") {  
            $Results += "<tr><td bgcolor=#eea0e8>{0} is not accessible.</td></tr><tr><td>&nbsp;</td></tr>" -f $job.location  
            ""  
            "--------- Error for {0} ---------" -f $job.location      
            Receive-Job -Id $job.Id   
        } else {  
            $Results += Receive-Job -Id $job.Id      
        }  
    }  
            
    $Results += "</table></body></html>"  
    $Results | out-file C:\temp\results.htm  
    Start-Process  C:\temp\results.htm  
       
    
    1 person found this answer helpful.
    0 comments No comments

  2. Dave Patrick 426.1K Reputation points MVP
    2022-11-21T13:44:55.837+00:00

    1, 2 you may be able to get from WSUS. 3, 4 you could possibly query the system event log.

    --please don't forget to upvote and Accept as answer if the reply is helpful--

    0 comments No comments