March 9, 2010

Scripting On the Fly

Okay so this code is not the elegant sort of code you see on other sites, it is truly a SysAdmin writing functional code while performing Admin functions (hence why the output is handle on the command line and not inside of the script). 

The patch released this past week to address the critical security vulnerability in Internet Explorer prompted action.  On a Friday evening the call went out to get all servers patched this weekend.  Having gone through this before I also knew someone will be asking for a report of what servers have been patched.  In the past I would have written something in vbscript. 

First step was to verify the WMI portion, to include the segment that would indicate the patch had been installed.  Going back one step, there had been a similar critical patch and was never able to get the Powershell code (V1) to work and ended up going with vbscript.  After verifying the WMI with some test cases, I passed on how to use Powershell to check a server to include offering my colleagues a WMIC alternative.

This code was tweaked several times, as the weekend progressed.  The final step was to provide more feedback.  At first it would just report, could not connect, installed and not installed.  I knew people would raise the eyebrows with that information.  I knew that things such as test-connection failing could be for several reasons and leaving it at “could not connect” would make the report suspect.  Also, the WMI query returning no data could mean the patch wasn’t installed but it could be because of other reasons such as Access Denied or RPC issues.

So the process was, patch a server while the code was running, keep checking the output looking for anomalies.  Then with some extra time I started looking at how I could include the current error data to the output instead of the generalized result I was presenting at first.

Below is the code, caution any of you Powershell purists because it might not be pretty but seems to work. :-)

#requires -Version 2
<#
.SYNOPSIS
      Checks for install status of KB978207.
.DESCRIPTION
      Uses a source file of server names, makes sure the server can be connected to,
      then uses WMI to query the QFE information.  Looks for the instance in the QFE
      where HotFixID matches 978207.  
.EXAMPLE
      c:\temp\run.ps1 | out-file c:\temp\audwstats.txt
.LINK
      http://www.microsoft.com/technet/security/bulletin/ms10-002.mspx
#>
function chk-updt {
$curError=$Error.count    # establish current index of the error variable
$qfedat = gwmi win32_quickfixengineering -computer $server  |  where {$_.hotfixid -like "*978207*"}
      #if no data is returned the qfedat variable will be null
      if ($qfedat -eq $Null){
      # Since no data was returned check to see if that was because of an error, if so report the 
      # returned error message
          if ($Error.count -gt $curError){$server + ": " + $Error[0].Exception.Message}
          # No error generated by WMI query so consider the patch not installed
          else {"Patch not installed on " + $server}
       } # Finished processing Null $qfedat
      # An instance was returned therefore the patch has been installed 
      else {$qfedat.HotFixID + " Installed on " + $server}
}  # end chk-updt
 
# Format report header
get-date
"-----------------------------------------------------------------------"
$ErrorActionPreference="SilentlyContinue"       # Keep the screen chatter done and continue after error
$noconnect=0
$servers = gc c:\temp\full.txt                              # Define array of server names from text file
foreach ($server in $servers) {
      # verify the server can be connected, if it can call the chk-updt function
      if (Test-Connection $server -Count 1){chk-updt}
      # if the server can not be connected, report the specific reason for failure
      else { $server + ": " + $error[0].Exception.Message
          $noconnect=$noconnect +1 }
}
"-----------------------------------------------------------------------"
"Servers Checked:  " + $servers.count 
"Servers not reachable: " + $noconnect
get-date

 


 


 



No comments:

Post a Comment