locked
Unexpected result of WMI query - Win32_ScheduledJob with VBScript RRS feed

  • Question

  • Hello, colleagues!
    I need your help to figure out unexpected result of WMI query - Win32_ScheduledJob with VBScript.
    The most strange thing - IF-STATEMENT IS EXECUTED, but must not.
    Pay your attention on code below:

    For Each strComputer In arrComputer
    		WScript.Echo "===================================="
    		WScript.Echo "Computer: "& strComputer
    		ThereIsTask = False
    		'By default suppose - there are no jobs on remote workstation
    		
    		WScript.Echo "ThereIsTask set to : " & ThereIsTask
    		Set objWMIService = GetObject("winmgmts:" _
    		& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    		'Getting WMI
    		
    		Set colScheduledJobs = objWMIService.ExecQuery _
    		("Select * from Win32_ScheduledJob")
    		'Query Scheduled Jobs from remote workstation
    		
    		For Each objJob in colScheduledJobs
    		'Iterate Scheduled Jobs on remote workstation
    				
    			If objJob.Command = "shutdown -s -f -t 00" Then
    			'If needed job exist of remote workstation 
    			'(EVEN IF REMOTE WORKSTATION UNAVAILABLE, IF-STATEMENT IS EXECUTED)
    					
    				ThereIsTask = True
    				'Set variable to True - there are jobs on remote workstation
    						
    				WScript.Echo "Command : " & objJob.Command & " exist of remote workstation"
    				'Not executed if workstation is unavailable
    						
    				WScript.Echo "ThereIsTask set to : " & ThereIsTask
    				Exit For
    			End If
    		Next
    		If ThereIsTask = False Then
    			'If needed job does not exist, output
    					
    			WScript.Echo "Computer: "& strComputer & " has no jobs created"
    			WScript.Echo "===================================="
    		End If
    	Next	

    Here is output:

    Microsoft (R) Windows Script Host Version 5.8
    Copyright (C) Microsoft Corporation. All rights reserved.
    
    ====================================
    Computer: PC01
    ThereIsTask set to : False
    ThereIsTask set to : True
    ====================================
    Computer: PC02
    ThereIsTask set to : False
    ThereIsTask set to : True
    ====================================
    Computer: PC04
    ThereIsTask set to : False
    ThereIsTask set to : True
    ====================================
    Computer: PC05
    ThereIsTask set to : False
    ThereIsTask set to : True
    ====================================
    Computer: PC06
    ThereIsTask set to : False
    ThereIsTask set to : True
    ====================================
    Computer: PC07
    ThereIsTask set to : False
    Command : shutdown -s -f -t 00 exist of remote workstation
    ThereIsTask set to : True
    ====================================
    Computer: PC08
    ThereIsTask set to : False
    Command : \shutdown -s -f -t 00 exist of remote workstation
    ThereIsTask set to : True
    ====================================
    Computer: PC09
    ThereIsTask set to : False
    Command : shutdown -s -f -t 00 exist of remote workstation
    ThereIsTask set to : True
    ====================================
    Computer: PC10
    ThereIsTask set to : False
    Command : shutdown -s -f -t 00 exist of remote workstation
    ThereIsTask set to : True
    ====================================
    Computer: PC11
    ThereIsTask set to : False
    Command : shutdown -s -f -t 00 exist of remote workstation
    ThereIsTask set to : True
    ====================================

    Workstations PC07 - PC11 are available and the output is correct.
    BUT IF REMOTE WORKSTATION UNAVAILABLE (workstations PC01 - PC06), IF-STATEMENT "If objJob.Command = "shutdown -s -f -t 00" Then" IS EXECUTED. But must not.
    WScript.Echo "Command : " & objJob.Command & " exist of remote workstation" is not executed on available workstations.
    Why "If objJob.Command = "shutdown -s -f -t 00" Then" returns true if workstation is unavailable?
    Thanks.

    P.S. I rewrote code with workstation availability checking and error handling - it works. But I want to figure out why code above returns wrong results.









    • Edited by fapw Friday, November 28, 2014 3:55 PM
    Friday, November 28, 2014 3:41 PM

Answers

  • Here is the full script:

    On Error Resume Next
    Set wshShell= CreateObject("WScript.Shell")
    Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
    
    

    continue to execute inside 'IF'. ThereIsTask = True etc?

    Thanks.

    Yes.  It will allow the script to continue even after a serious error and the error will never be reported.  It is a very bad idea to start a scrip t with "On Error Resume Next".  Follow Bill's advice.  Remove it and fix the error.  Use muy examples for ways to simplify your script so that you can understand what it is doing.

    The "One Error Resume Next"statement tells VBScript that yo are going to manage the errors yourself.  That tells the system to never display an error or stop on an error.  If you use that stement then you must check for error s on all lines that can produce and error and handle the error.

    Start here for more info: http://blogs.msdn.com/b/ericlippert/archive/2004/08/19/error-handling-in-vbscript-part-one.aspx


    ¯\_(ツ)_/¯

    • Marked as answer by fapw Friday, November 28, 2014 6:01 PM
    Friday, November 28, 2014 5:59 PM
  • Redesign the script logic so it works without On Error Resume Next at the top of the script.

    Do not use On Error Resume Next unless you understand exactly what it does and how it works.

    Reading the VBScript documentation will be helpful in this regard.


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by fapw Friday, November 28, 2014 6:15 PM
    Friday, November 28, 2014 5:23 PM
  • If you have On Error Resume Next it will cause you to continue after an error.  Any script execution after that can execute almost any line of code.

    Without your full script or a short sample that reproduces the problem we cannot be of any more help than that.


    ¯\_(ツ)_/¯

    • Marked as answer by fapw Friday, November 28, 2014 6:05 PM
    Friday, November 28, 2014 5:32 PM
  • What we are saying is to write a SSCCE. Read this: http://sscce.org/

    That is, you need to write a short script that contains only the absolute minimum amount of code needed to reproduce the problem. In so doing, you will have much better success in identifying and fixing it yourself, and you will probably learn a lot in the process.


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by fapw Friday, November 28, 2014 6:04 PM
    Friday, November 28, 2014 5:55 PM

All replies

  • I am guessing you are using On Error Resume Next in your script.

    Remove that as a first debugging step.


    -- Bill Stewart [Bill_Stewart]

    Friday, November 28, 2014 4:32 PM
  • I am guessing you are using On Error Resume Next in your script.

    Remove that as a first debugging step.


    -- Bill Stewart [Bill_Stewart]

    Yes, you are right. If to remove it, I'll get of course Microsoft VBScript runtime error: The remote server machine does not exist or is unavailable: 'GetObject'

    But my goal is not to make the script work (I did it by adding availability checking and error handling, removed 'On Error Resume Next' too). My goal, to examine why "If objJob.Command = "shutdown -s -f -t 00" Then" returns true if workstation is unavailable?

    Thanks,


    • Edited by fapw Friday, November 28, 2014 5:19 PM
    Friday, November 28, 2014 5:18 PM
  • Redesign the script logic so it works without On Error Resume Next at the top of the script.

    Do not use On Error Resume Next unless you understand exactly what it does and how it works.

    Reading the VBScript documentation will be helpful in this regard.


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by fapw Friday, November 28, 2014 6:15 PM
    Friday, November 28, 2014 5:23 PM
  • Redesign the script logic so it works without On Error Resume Next at the top of the script.

    Do not use On Error Resume Next unless you understand exactly what it does and how it works.

    Reading the VBScript documentation will be helpful in this regard.


    -- Bill Stewart [Bill_Stewart]

    This is my script and I understand how it works. After querying Scheduled Jobs from unavailable remote workstation colScheduledJobs must be empty. And therefore objJob.Command must be empty. But what I cannot understand, if objJob.Command is empty, why 'If objJob.Command = "shutdown -s -f -t 00" Then' returns true?

    Thanks.


    • Edited by fapw Friday, November 28, 2014 5:30 PM
    Friday, November 28, 2014 5:30 PM
  • If you have On Error Resume Next it will cause you to continue after an error.  Any script execution after that can execute almost any line of code.

    Without your full script or a short sample that reproduces the problem we cannot be of any more help than that.


    ¯\_(ツ)_/¯

    • Marked as answer by fapw Friday, November 28, 2014 6:05 PM
    Friday, November 28, 2014 5:32 PM
  • Use this to help debug your issue:

    For Each strComputer In arrComputer
    
        On Error GoTo 0
    
        WScript.Echo "===================================="
        WScript.Echo "Computer: "& strComputer
        ThereIsTask = False
        
        WScript.Echo "ThereIsTask set to : " & ThereIsTask
        Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
        Set colScheduledJobs = objWMIService.ExecQuery("Select * from Win32_ScheduledJob")
        
        WScript.Echo "JOBS:" & colScheduledJobs.Count
        For Each objJob in colScheduledJobs
            WScript.Echo "COMMAND:" & objJob.Command	
            If objJob.Command = "shutdown -s -f -t 00" Then
                ThereIsTask = True
                WScript.Echo "Command : " & objJob.Command & " exist of remote workstation"
                WScript.Echo "ThereIsTask set to : " & ThereIsTask
                Exit For
            End If
        Next
        
        If ThereIsTask = False Then
            WScript.Echo "Computer: "& strComputer & " has no jobs created"
            WScript.Echo "===================================="
        End If
    
    Next	

    This  will help to find your issue. 

    It is also possible to have a corrupt file or disk that will cause runaway code.  Simplifying to the fewest lines possible can help to find the exact bug.


    ¯\_(ツ)_/¯

    Friday, November 28, 2014 5:40 PM
  • Here is a more standard way of doing what you are trying to do.

    For Each strComputer In arrComputer
        If GetJobs(strComputer) Then
            WScript.Echo "Command exists on " & strComputer
        Else
            WScript.Echo strComputer & " has no jobs created"
        End If
    Next
    
    Function GetJobs(strComputer)
        On Error GoTo 0
        Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
        Set colScheduledJobs = objWMIService.ExecQuery("Select * from Win32_ScheduledJob")
    
        For Each objJob in colScheduledJobs
             If objJob.Command = "shutdown -s -f -t 00" Then
                GetJobs = True
                Exit Function
            End If
        Next
         
    End Function


    ¯\_(ツ)_/¯



    • Edited by jrv Friday, November 28, 2014 5:48 PM
    Friday, November 28, 2014 5:46 PM
  • If you have On Error Resume Next it will cause you to continue after an error.  Any script execution after that can execute almost any line of code.

    Without your full script or a short sample that reproduces the problem we cannot be of any more help than that.


    ¯\_(ツ)_/¯

    Here is the full script:

    On Error Resume Next
    Set wshShell= CreateObject("WScript.Shell")
    Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
    
    'Define the array of workstations
    arrComputer = Array(_
    "PC01", _  
    "PC02", _  
    "PC04", _  
    "PC05", _
    "PC06", _
    "PC07", _
    "PC08", _
    "PC09", _
    "PC10", _
    "PC11" _
    )
    
    For Each strComputer In arrComputer
    	WScript.Echo "===================================="
    	WScript.Echo "Computer: "& strComputer
    	ThereIsTask = False
    	'By default suppose - there are no jobs on remote workstation
    		
    	WScript.Echo "ThereIsTask set to : " & ThereIsTask
    	Set objWMIService = GetObject("winmgmts:" _
    	& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    	'Getting WMI
    		
    	Set colScheduledJobs = objWMIService.ExecQuery _
    	("Select * from Win32_ScheduledJob")
    	'Query Scheduled Jobs from remote workstation
    		
    	For Each objJob in colScheduledJobs
    	'Iterate Scheduled Jobs on remote workstation
    				
    		If objJob.Command = "shutdown -s -f -t 00" Then
    		'If needed job exist of remote workstation 
    		'(EVEN IF REMOTE WORKSTATION UNAVAILABLE, IF-STATEMENT IS EXECUTED)
    					
    			ThereIsTask = True
    			'Set variable to True - there are jobs on remote workstation
    						
    			WScript.Echo "Command : " & objJob.Command & " exist of remote workstation"
    			'Not executed if workstation is unavailable
    						
    			WScript.Echo "ThereIsTask set to : " & ThereIsTask
    			Exit For
    		End If
    	Next
    	If ThereIsTask = False Then
    	'If needed job does not exist, output
    					
    		WScript.Echo "Computer: "& strComputer & " has no jobs created"
    		WScript.Echo "===================================="
    	End If
    Next


    jrv, do you want to say, if I declare 'On Error Resume Next' in the beginning, this peace of code

    If objJob.Command = "shutdown -s -f -t 00" Then
    	'If needed job exist of remote workstation 
    	'(EVEN IF REMOTE WORKSTATION UNAVAILABLE, IF-STATEMENT IS EXECUTED)
    					
    		ThereIsTask = True
    		'Set variable to True - there are jobs on remote workstation
    						
    		WScript.Echo "Command : " & objJob.Command & " exist of remote workstation"
    		'Not executed if workstation is unavailable
    						
    		WScript.Echo "ThereIsTask set to : " & ThereIsTask
    		Exit For
    End If

    continue to execute inside 'IF', independently result of true of false?. ThereIsTask = True etc?

    Thanks.


    • Edited by fapw Friday, November 28, 2014 5:52 PM
    Friday, November 28, 2014 5:50 PM
  • This is how to build a simple solution./  Only add all of the fancy formatting after you have the solution worked out.  Most non-programmers and some programmers get lost in the comments and formatting and cannot see the problem.

    Mixing "output format" with "data collection" is a no-no in the world of programming and scripting. It leads to "spaghetti code" which is even banned in Italy.  It also leads to very hard to debug scripts.


    ¯\_(ツ)_/¯

    Friday, November 28, 2014 5:50 PM
  • What we are saying is to write a SSCCE. Read this: http://sscce.org/

    That is, you need to write a short script that contains only the absolute minimum amount of code needed to reproduce the problem. In so doing, you will have much better success in identifying and fixing it yourself, and you will probably learn a lot in the process.


    -- Bill Stewart [Bill_Stewart]

    • Marked as answer by fapw Friday, November 28, 2014 6:04 PM
    Friday, November 28, 2014 5:55 PM
  • Here is the full script:

    On Error Resume Next
    Set wshShell= CreateObject("WScript.Shell")
    Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
    
    

    continue to execute inside 'IF'. ThereIsTask = True etc?

    Thanks.

    Yes.  It will allow the script to continue even after a serious error and the error will never be reported.  It is a very bad idea to start a scrip t with "On Error Resume Next".  Follow Bill's advice.  Remove it and fix the error.  Use muy examples for ways to simplify your script so that you can understand what it is doing.

    The "One Error Resume Next"statement tells VBScript that yo are going to manage the errors yourself.  That tells the system to never display an error or stop on an error.  If you use that stement then you must check for error s on all lines that can produce and error and handle the error.

    Start here for more info: http://blogs.msdn.com/b/ericlippert/archive/2004/08/19/error-handling-in-vbscript-part-one.aspx


    ¯\_(ツ)_/¯

    • Marked as answer by fapw Friday, November 28, 2014 6:01 PM
    Friday, November 28, 2014 5:59 PM
  • Now that we have simplified we can easily handle errors.  Here is an example of how it is done:

    For Each strComputer In arrComputer
    
        WScript.Echo "===================================="
        WScript.Echo "Computer: "& strComputer
        If GetJobs(strComputer) Then
                WScript.Echo vbTab & "Command exists on remote workstation"
        Else
            WScript.Echo vbTab & "Computer has no jobs created"
        End If
    Next
    
    Function GetJobs(strComputer)
        On Error Resume Next
        Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
        If Err.Number <> 0 Then
            WScript.Echo Err.Description
            Exit Function
        End If
        
        On Error GoTo 0
        Set colScheduledJobs = objWMIService.ExecQuery("Select * from Win32_ScheduledJob")
        WScript.Echo "JOBS:" & colScheduledJobs.Count
        For Each objJob in colScheduledJobs
            WScript.Echo "COMMAND:" & objJob.Command	
            If objJob.Command = "shutdown -s -f -t 00" Then
                GetJobs = True
                Exit Function
            End If
        Next
         
    End Function

    Notice that we still have to turn error handling back on or return it to the system incase ther is another error on any of the subsequent calls.  There shouldn't be but if ther eis we want to abort and fix the problem.

    Of course you can also ping the computer but the call may still fail due to RPC errors or other issues.  This collects and reports all errors.

    Of course all of this is much easier with PowerShell.


    ¯\_(ツ)_/¯


    • Edited by jrv Friday, November 28, 2014 6:06 PM
    Friday, November 28, 2014 6:05 PM
  • jrvBill_Stewart thank you guys. Now I understand. Thank you for advises.

    Have a nice day.


    • Edited by fapw Friday, November 28, 2014 6:11 PM
    Friday, November 28, 2014 6:07 PM
  • Thank you.  Good luck.

    ¯\_(ツ)_/¯

    Friday, November 28, 2014 6:09 PM