Friday, August 30, 2013

Lightweight SCCM and WMI problem scanner

While troubleshooting, I needed a way to scan a bunch of machines looking for common problems with SCCM clients and WMI.  The main goal was to check those 3 area's of WMI so that I could focus on machines that needed WMI repaired.  I know you can do this w/ Client Center and other tools but I like a tool that I can tweak so hopefully this gets someone else off to a good start. 

If you copy it, beware the word wrap on the hardware inventory action ID trigger.  There are a few things specific to my environment, so if you're not using client version 5.00.7804.1202 for example, that'll have to be tweaked.

'---------------------------------------------------------------------------
'                           SCCM 2012 Pinger                               

'                                                                          
' AUTH: David Bennett                                                      
'                                                                          
' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY   
' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE      
' IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR    
' PURPOSE.                                                                 
'                                                                          
' Use : cscript PingEm.vbs                                                 
' Desc: Pings a list of systems and does light diagnostics on WMI          
' In  : Expects a list of machines, one per line, named Ping__List.txt     
' Out : Drops two logs                                                     
'       Log_Output.log contains good results                         
'       Log_BadSys.log contains systems with errors (timed out, WMI etc)       
' Note: There are two items that need to be set to your envinronment       
'       They are surronded by <-delimeters->       
'       It's looking for Domain1\UserName                                 
'---------------------------------------------------------------------------


Option Explicit
On Error Resume Next
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8

Dim strInputName  : strInputName = "Ping__List.txt"
Dim FSO   : Set FSO = CreateObject("Scripting.FileSystemObject")
Dim WshShell   : Set WshShell = CreateObject("wscript.shell")
Dim objWMISvc
Dim colItems
Dim objItem
Dim objFile
Dim PingIT


Dim oFile : Set oFile = FSO.CreateTextFile("Ping_Output.log",2)
Dim bFile : Set bFile = FSO.CreateTextFile("Ping_BadSystems.log",2)
Dim iFile : Set iFile = FSO.OpenTextFile(strInputName, 1)


Dim strComputer
Dim strResult
Dim strReply
Dim strUsage
Dim strVersion
Dim strFileDate
Dim strOutput
Dim strOutBad
Dim strOutGood
Dim strInvType
Dim strIP
Dim strOS


Dim boolBad

If NOT FSO.FileExists(strInputName) Then
 strUsage = Msgbox("The file, " & strInputName & " is not available")
 wscript.quit
End If


Do Until iFile.AtEndOfStream
 strComputer = iFile.Readline

 Set PingIT = WshShell.exec("ping -n 2 " & strComputer)
 Do Until PingIT.status = 1 : wscript.sleep 10 : loop
  strResult = pingIT.stdout.readall

  Select Case True
  Case InStr(strResult, "timed out") > 1
   boolBad = 1
   strReply = "Timed Out" & VBTab
   strIP = GetIP(strResult) & VBTab
  Case InStr(strResult, "could not find host") > 1
   boolBad = 1
   strReply = "No DNS Record" & VBTab
   strIP = "N/A" & VBTab
  Case InStr(strResult, "Destination host unreachable") > 1
   boolBad = 1
   strReply = "Unreachable" & VBTab
   strIP = GetIP(strResult) & VBTab
  Case InStr(strResult, "Reply from") > 1
   boolBad = 0
   strReply = "Success" & VBTab
   strIP = GetIP(strResult) & VBTab
  Case Else
   boolBad = 1
   strOutput = strOutput & "UNK Error in Ping: " & err.Number & ", " & err.description & VBTab
  End Select


 If boolBad = 0 Then
  Set objWMISvc=GetObject("winmgmts:{impersonationlevel=impersonate}!\\" & strComputer &"\root\ccm")
  If err.number<>0 Then
   boolBad = 1
   strOutput = strOutPut & "CCM WMI Access Error: " & err.Number & ", " & err.description & VBTab
   err.clear
  Else
   Set colItems = objWMISvc.ExecQuery("Select * from SMS_Client")
   If err.number<>0 Then
    boolBad = 1
    strOutput = strOutPut & "WMI Query Error: " & err.Number & ", " & err.description & VBTab
    err.clear
   Else
    For Each objItem in colItems
     strVersion = objItem.ClientVersion
     strOutput = strOutput & "Version " & strVersion & VBTab
    Next
   End If
   If Left(strVersion, 12) <> "5.00.7804.12" Then
    boolBad = 1
   End If
  End If


  Set objWMISvc=GetObject("winmgmts:{impersonationlevel=impersonate}!\\" & strComputer &"\root\ccm\invagt")
  If err.number<>0 Then
   boolBad = 1
   strOutput = strOutPut & "Invagt WMI Access Error: " & err.Number & ", " & err.description & VBTab
   err.clear
  Else
   Set colItems = objWMISvc.ExecQuery("Select * from InventoryActionStatus Where InventoryActionID = '{00000000-0000-0000-0000-000000000001}'")
   If err.number<>0 Then
    boolBad = 1
    strOutput = strOutPut & "WMI Query Error: " & err.Number & ", " & err.description & VBTab
    err.clear
   Else
    For Each objItem in colItems
     strFileDate = GetDate(objItem.LastCycleStartedDate)
    Next
   End If
   If Right(strFileDate, 4) = "2013" Then
    strOutPut = strOutput & "Invdate: " & strFileDate & VBTab
   Else
    strOutPut = strOutput & "InvDate: Invalid" & VBTab
   End If
  End If

  Set ObjWMISvc = GetObject("winmgmts:{impersonationlevel=impersonate}!\\" & strComputer &"\root\cimv2")
  If err.number<>0 Then
   boolBad = 1
   strOutput = strOutPut & "CIMv2 WMI Access Error: " & err.Number & ", " & err.description & VBTab
   err.clear
  Else
   Set colItems = objWMISvc.ExecQuery("Select * from Win32_OperatingSystem")
   If err.number<>0 Then
    boolBad = 1
    strOutput = strOutPut & "WMI Query Error: " & err.Number & ", " & err.description & VBTab
    err.clear
   Else
    For Each objItem in colItems
     strOS = objItem.Caption
     strOutput = strOutPut & "OS " & strOS & VBTab
    Next
   End If
  End If

 End If

 If boolBad = 1 Then
  strOutBad = strComputer & VBTab & strReply & VBTab & strIP & VBTab & strOutput
  bFile.WriteLine(strOutBad)
  wscript.echo "Bad " & strOutbad
  strOutBad = ""
 Else
  strOutGood = strComputer & VBTab & strReply & VBTab & strIP & VBTab & strOutput
  oFile.WriteLine(strOutGood)
  wscript.echo "Good " & strOutPut
  strOutGood = ""
 End If


 strVersion = ""
 strFileDate = ""
 boolBad = 0
 strOutput = ""
 strFileDate = ""


Loop

Function GetIP(ByVal reply)
 Dim FindIP
 FindIP = Instr(reply, "[")
 If FindIP = 0 Then
  Exit Function
 End If
 reply = Mid(reply, FindIP+1)
 FindIP = InStr(reply, "]")
 If FindIP = 0 Then
  Exit Function
 End If
 GetIP = Left(reply,FindIP-1)
End Function


Function GetDate(Serial)
 GetDate = mid(Serial,5,2) & "-" & mid(Serial,7,2) & "-" & left(Serial,4)
End Function

No comments:

Post a Comment