Web Images Videos Maps News Shopping Google Mail more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Message from discussion MBSACLI 2.0 /xmlout Parsing Script

View Parsed - Show only message text

Date: Mon, 11 Jul 2005 18:02:42 +0200
From: "Torgeir Bakken \(MVP\)" <Torgeir.Bakken-s...@hydro.com>
Organization: Gjett to ganger
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040113
X-Accept-Language: en-us
MIME-Version: 1.0
Subject: Re: MBSACLI 2.0 /xmlout Parsing Script
References: <lutoc1hmhs2lib90n9c8g3q36rlfpk2qck@4ax.com>
In-Reply-To: <lutoc1hmhs2lib90n9c8g3q36rlfpk2qck@4ax.com>
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Message-ID: <edBIeKjhFHA.3652@TK2MSFTNGP10.phx.gbl>
Newsgroups: microsoft.public.security.baseline_analyzer
NNTP-Posting-Host: 44-49-164-136.hydro.com 136.164.49.44
Path: g2news1.google.com!news4.google.com!newshub.sdsu.edu!msrtrans!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP10.phx.gbl
Lines: 1         

Andrew Aronoff wrote:

> I have written a VBS script that runs MBSACLI 2.0 with the /xmlout
> option and parses the XML output file to produce a readable text file.
> 
> The script can be downloaded here:
> http://www.silentrunners.org/MBSACLI%20XML%20Parser.vbs
> (snip)
Hi,

Further down in this post is another mbsacli.exe /xmlout parse script
(that I have written).

Some comment first:

In the thread "MBSACLI 2.0 XML tags", you wrote:

"BTW, I noticed that when Windows Update Agent 2.0 is not installed,
nothing is added to the XML file. That's too bad."

The reason for this is that the error messages from mbsacli.exe goes
to StdErr, while you only redirect StdOut (where all the "normal"
output goes to.

To redirect StdErr to a separate file, use " 2>SomeFile", here is a
snippet from the full script below:
'--------------------8<----------------------
' As the ShortPath property have been used for all paths, extra
' quotes are not needed
sCmd = "%comspec% /c " & sMBSAFilePath & " " & sMBSACmdSwitches _
   & " >" & sXMLFilePath & " 2>" & sStdErrFilePath
'--------------------8<----------------------

One small issue here is that mbsacli adds header information to this
error file even when no errors have arised, so you will need to skip
the first 4 lines in that file. See the use of the function CheckStdErr
below for how I have handled this.

Also, I have used Microsoft's XML DOM (MSXML2.DOMDocument) to parse
the XML file.


Here is the full script:

'--------------------8<----------------------

Option Explicit

' Script that parses the output from MBSA 2.0's mbsacli.exe
' (using the /xmlout switch). Any errors in the StdErr is
' also picked up.
'
' Script is reporting both installed and missing updates. See
' the comments for the sXPath variable on how to change it to
' report only on installed or missing updates.
'
' Author: Torgeir Bakken
' Date: 2005-07-11


Const OverwriteIfExist = -1
Const OpenAsASCII   =  0

Dim sReportFile, sXMLFilePath, sXPath, oXMLDoc, oErr, oFSO, oShell
Dim sMsgBoxTitle, sStdErr, sStdErrFilePath, sMBSAFilePath
Dim sCabFilePath, sMBSACmdSwitches, sCmd

' -------  Section with variables you can/must change  -------

' Path and name of status text file to be created
' Environment variables allowed
sReportFile = "%tmp%\UpdateStatus.txt"

' Path and name of mbsacli.exe, environment variables allowed
sMBSAFilePath = "C:\mbsa2\mbsacli.exe"

' Path and name of wsusscan.cab, environment variables allowed.
' Note that microsoft does not support placement on a network drive.
' Set it to "" if you do not want to use the /catalog switch
' If this string is not empty (""), /catalog <cab file path> will
' be added to the command line of mbsacli.exe
sCabFilePath = "C:\mbsa2\wsusscan.cab"

' Command line switches to be used for mbsacli.exe
' Using /xmlout to run in updates only mode using only mbsacli.exe
' and wusscan.dll. Only these switches can be used with this option:
' /catalog, /wa, /wi, /nvc, /unicode
sMBSACmdSwitches = "/xmlout /nvc"

sXPath = "//UpdateData"
' To list only installed updates, use this one instead:
'sXPath = "//UpdateData[@IsInstalled='true']"
' To list only missing updates, use this one instead:
'sXPath = "//UpdateData[@IsInstalled='false']"

' Title to be used by MsgBox commands
sMsgBoxTitle = "MBSA Update Check"


' -------  Section that prepares for running mbsacli.exe  -------

Set oShell = CreateObject("WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")


sMBSAFilePath = oShell.ExpandEnvironmentStrings(sMBSAFilePath)
If oFSO.FileExists(sMBSAFilePath) Then
   sMBSAFilePath = oFSO.GetFile(sMBSAFilePath).ShortPath
Else
   MsgBox sMBSAFilePath & " does not exist!", _
      vbCritical + vbSystemModal, sMsgBoxTitle
   WScript.Quit
End If

If sCabFilePath <> "" Then
   sCabFilePath = oShell.ExpandEnvironmentStrings(sCabFilePath)
   If oFSO.FileExists(sCabFilePath) Then
     sCabFilePath = oFSO.GetFile(sCabFilePath).ShortPath
     sMBSACmdSwitches = sMBSACmdSwitches & " /catalog " & sCabFilePath
   Else
     MsgBox sCabFilePath & " does not exist!", _
        vbCritical + vbSystemModal, sMsgBoxTitle
     WScript.Quit
   End If
End If

' Get a temporary file name for xml file MbsaCli.exe creates
Do
   sXMLFilePath = oFSO.GetSpecialFolder(2).ShortPath _
      & "\" & oFSO.GetTempName
Loop While oFSO.FileExists(sXMLFilePath)

' Get a temporary file name for the stderr file MbsaCli.exe creates
Do
   sStdErrFilePath = oFSO.GetSpecialFolder(2).ShortPath _
      & "\" & oFSO.GetTempName
Loop While oFSO.FileExists(sStdErrFilePath)


' As the ShortPath property have been used for all paths, extra
' quotes are not needed
sCmd = "%comspec% /c " & sMBSAFilePath & " " & sMBSACmdSwitches _
   & " >" & sXMLFilePath & " 2>" & sStdErrFilePath


' -------  Section that runs mbsacli.exe and checks the result  -------

oShell.Run sCmd, 0, True

sStdErr = CheckStdErr(sStdErrFilePath)

On Error Resume Next
oFSO.DeleteFile sStdErrFilePath
On Error Goto 0

If sStdErr <> "" Then
   MsgBox "MBSA failed, error was:" & vbNewLine & vbNewLine & sStdErr, _
      vbCritical + vbSystemModal, sMsgBoxTitle

   On Error Resume Next
   oFSO.DeleteFile sXMLFilePath
   On Error Goto 0
   WScript.Quit
End If

' -------  Section that parses the output in the xml file  -------

Set oXMLDoc = CreateObject("MSXML2.DOMDocument")
oXMLDoc.SetProperty "SelectionLanguage", "XPath"
oXMLDoc.Async = False

oXMLDoc.Load sXMLFilePath

If (oXMLDoc.parseError.errorCode <> 0) Then

   Set oErr = oXMLDoc.ParseError
   MsgBox "Could not load file " & sXMLFilePath _
     & " , error: " & oErr.Reason, _
       vbCritical + vbSystemModal, sMsgBoxTitle

   WScript.Quit
End If


Dim dicElements, oNodes, oElement
Dim sGUID, sKBID, sBulletinID, iType, iSeverity, bRestartRequired
Dim bIsInstalled, sTitle, sBulletinURL, sInformationURL, sDownloadURL
Dim sType, sSeverity

' use a dictionary object to filter out double entries (will
' exist e.g. for WSUS scans).
Set dicElements = CreateObject("Scripting.Dictionary")
dicElements.CompareMode = vbTextCompare

Set oNodes = oXMLDoc.DocumentElement.SelectNodes(sXPath)

On Error Resume Next
For Each oElement in oNodes

   sGUID = ""  ' init value
   sGUID = oElement.getAttribute("GUID")

   If Not dicElements.Exists(sGUID) Then
     ' init values
     sKBID = "": sBulletinID = "": iType = "": iSeverity = ""
     bIsInstalled = "": bRestartRequired = "": sTitle = ""
     sBulletinURL = "": sInformationURL = "": sDownloadURL = ""
     sType = "": sSeverity = ""

     sKBID = oElement.getAttribute("KBID")
     sBulletinID = oElement.getAttribute("BulletinID")

     iType = CInt(oElement.getAttribute("Type"))
     Select Case iType
       Case 1
         sType = "Security Update"
       Case 2
         sType = "Service Pack"
       Case 3
         sType = "Update Rollup"
     End Select

     iSeverity =  CInt(oElement.getAttribute("Severity"))
     Select Case iSeverity
       Case 0
         sSeverity = "(no rating)"
       Case 1
         sSeverity = "Low"
       Case 2
         sSeverity = "Moderate"
       Case 3
         sSeverity = "Important"
       Case 4
         sSeverity = "Critical"
     End Select

     bIsInstalled = CBool(oElement.getAttribute("IsInstalled"))
     bRestartRequired = CBool(oElement.getAttribute("RestartRequired"))
     sTitle = oElement.selectSingleNode("Title").text

     sBulletinURL = oElement.selectSingleNode _
          ("References/BulletinURL").text

     sInformationURL = oElement.selectSingleNode _
          ("References/InformationURL").text

     sDownloadURL = oElement.selectSingleNode _
          ("References/DownloadURL").text

     ' using the GUID value as dictionary key
     dicElements.Add sGUID, _
       Array( _
         sKBID, _
         sBulletinID, _
         sType, _
         sSeverity, _
         bIsInstalled, _
         bRestartRequired, _
         sTitle, _
         sBulletinURL, _
         sInformationURL, _
         sDownloadURL)
   End If

Next
oFSO.DeleteFile sXMLFilePath
On Error Goto 0


' -------  Section that creates the report file  -------

If dicElements.Count = 0 Then
   WScript.Echo "No updates found"
Else
   Dim f
   Set f = oFSO.CreateTextFile( _
      oShell.ExpandEnvironmentStrings(sReportFile), _
      OverwriteIfExist, OpenAsASCII)

   f.WriteLine "Report on update status run at " & Now
   f.WriteLine "---------------------------------" _
        & "---------------------------------"
   f.WriteLine
   f.WriteLine "Total number of update entries found: " _
      & dicElements.Count
   f.WriteLine "---------------------------------" _
        & "---------------------------------"
   f.WriteLine

   f.WriteLine "Installed updates:" & vbNewLine
   ListElements (True)

   f.WriteLine "---------------------------------" _
        & "---------------------------------"
   f.WriteLine
   f.WriteLine "Missing updates:" & vbNewLine
   ListElements (False)

   f.Close

   oShell.Run "notepad.exe " & """" & sReportFile & """", 1, False

End If


' Start functions and subs

Function CheckStdErr(ByVal sFile)

   Const OpenAsASCII      =  0
   Const FailIfNotExist   =  0
   Const ForReading       =  1

   Dim oFSO, fFile, i, sValue, sLine

   Set oFSO = CreateObject("Scripting.FileSystemObject")

   If oFSO.GetFile(sFile).Size = 0 Then
     CheckStdErr = "Something is wrong, StdErr file size is 0 byte!"
     Exit Function    ' ----->
   End If

   Set fFile = oFSO.OpenTextFile(sFile, ForReading, _
                 FailIfNotExist, OpenAsASCII)

   ' Skip first 4 lines that always just contains the same header info
   For i = 1 To 4
     fFile.SkipLine
   Next

   sValue = ""   ' init value

   'Parse the rest of the text file
   Do While Not fFile.AtEndOfStream
     sLine = fFile.Readline
     If sLine <> "" Then
       If sValue = "" Then
         sValue = sLine
       Else
         sValue = sValue & vbNewLine & sLine
       End If
     End If
   Loop

   fFile.Close

   CheckStdErr = sValue

End Function


Sub ListElements(ByVal bInstallStatus)

   Dim sDicElement
   For Each sDicElement In dicElements
     If dicElements.Item(sDicElement)(4) = bInstallStatus Then
       f.WriteLine "KB ID: " & dicElements.Item(sDicElement)(0)
       f.WriteLine "Bulletin ID: " & dicElements.Item(sDicElement)(1)
       f.WriteLine "Type: " & dicElements.Item(sDicElement)(2)
       f.WriteLine "Severity: " & dicElements.Item(sDicElement)(3)
       If bInstallStatus Then
         f.WriteLine "Restart Required: " _
           & dicElements.Item(sDicElement)(5)
       End If
       f.WriteLine "Title: " & dicElements.Item(sDicElement)(6)
       f.WriteLine "Bulletin URL: " & dicElements.Item(sDicElement)(7)
       f.WriteLine "Information URL: " & dicElements.Item(sDicElement)(8)
       f.WriteLine "Download URL: " & dicElements.Item(sDicElement)(9)
       f.WriteLine
     End If
   Next

End Sub

'--------------------8<----------------------





-- 
torgeir, Microsoft MVP Scripting and WMI, Porsgrunn Norway
Administration scripting examples and an ONLINE version of
the 1328 page Scripting Guide:
http://www.microsoft.com/technet/scriptcenter/default.mspx

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google