Prepare!

Lee Harvey's Zombie Hit Parade

Returning an errorlevel from WSH VBScripts

, , , , ,

Most people complain that cscript.exe (Windows Scripting Host) always returns an errorlevel of 0 (zero) to its parent batch process after running WSH scripts, even when the script dies with a known Err.Number. Others complain that their calls to WScript.Quit Err.Number never get called because the script dies before the script gets a chance to call WScript.Quit. And using the horrid On Error Resume Next is simply out of the question here.

So what gives, is there a solution? YES!

The trick is using the information from my previous VBScript post, and strategically handling errors inside the VBScript Class_Terminate() event -- which is guaranteed to be called, even if your script dies during Class_Initialize()

For example:

Option Explicit

Dim exitcode : exitcode = 0

Class Global
   Private Sub Class_Initialize()
      s  = "" ' Generate an undefined variable error
   End Sub

   Private Sub Class_Terminate()
      exitcode = Err.Number
   End Sub	
End Class

Dim Main : Set Main = New Global
Set Main = Nothing

WScript.Quit exitcode

As a result of saving-off any errors in the final Class_Terminate() event handler, you can adequately return the WSH error code to your parent batch command script for further processing, like so:

@echo off
cscript.exe //NoLogo //E:VBScript test.vbs
if errorlevel == 500 echo An undefined variable exists!

...and so forth.

As you can see, this is pretty simple, but most VBScript programmers simply aren't aware of the Class statement introduced in VBScript 5. As such, I rarely ever see it being used out in-the-wild; which is unfortunate.

Hope this helps. Enjoy.

NetFlix has a sense of humorSoftware and driver updates

Comments

jefftanner Sunday, November 9, 2008 6:22:39 AM

I saw your post and I am wondering how you got WScript.Quit() to work. What do I need to do within a JScript program to flag the calling CScript.exe utility that an error occurred within the program, and thereby CScript.exe then sets the DOS ERRORLEVEL to one (1) ? I have tried the following, and I cannot get %ERRORLEVEL% to be set to three (3) after using WScript.Quit(3) within either VBScript or JScript files. Here is my code. What I am doing wrong?
QuitTest.cmd @ECHO OFF ECHO. cscript //NoLogo QuitTest.vbs ECHO QuitTest.vbs: %errorlevel% ECHO. cscript //NoLogo QuitTest.js ECHO QuitTest.js: %errorlevel%
QuitTest.js WScript.Echo("JScript QuitTest"); WScript.Quit(3);
QuitTest.vbs WScript.Echo("VBScript QuitTest") WScript.Quit(3) The results after the following run were that neither the VBScript not the JScript usage of WScript.Quit(3) set the %ERRORLEVEL% to 3.
DOS Run... D:\Workspace>QuitTest.cmd VBScript QuitTest QuitTest.vbs: 0 JScript QuitTest QuitTest.js: 0 Thanks Jeff in Seattle

Lee HarveyLee_Harvey Sunday, November 9, 2008 1:33:22 PM

This seems to work for me...

test.js
WScript.Echo("JScript QuitTest"); 
WScript.Quit(3);

test.bat
@echo off
cscript.exe //nologo //e:jscript test.js
echo %errorlevel%

Output
JScript QuitTest
3


...although, I wouldn't recommend returning 3 as an errorlevel from your WSH scripts. Why? Because 3 is a valid Windows network message number. Therefore, try returning error numbers that do not coincide/clash with valid Windows network message numbers. For example, net helpmsg 3 coincides with message "The system cannot find the path specified" -- which is not the case here.

For testing purposes, -3 might be more appropriate.

HTH

keithel Tuesday, December 2, 2008 8:08:08 PM

I thought I'd drop in and say that what you've uncovered is quite handy!
I did a rewrite to make this more of a singleton, and requiring no need to store off the exitcode, and no need to add 'WScript.Quit exitcode' at the end of your script...

Without the exclusion of of the odd '-2147155971' Err.Number, explicit WScript.Quit calls within the main body of the script will fail to make the script return the exit code desired -- instead the class terminate will trigger and return the large negative error code above.

Here's my rewrite:

option explicit

' Put this class and it's primitive singleton-like initializer
' at the top of your script.
' This class makes sure that wsh/vbscript runtime errors are caught
' and returned as ERRORLEVEL when the script exits.  If you don't
' do this, runtime errors will still result in the caller of this
' script receiving 0 (success) error code.
Class QuitErrorlevelOnRuntimeError
   Private Sub Class_Terminate()
      ' When 'WScript.Quit' is called, it seems to set err.Number 
      ' to -2147155971.  Since we want the quit to return it's 
      ' error code, don't return err.number if this err.number is 
      ' seen
      dim quitErrNum : quitErrNum = -2147155971
      if Err.Number <> 0 and Err.Number <> quitErrNum then
        'WScript.echo "Err " & Err.Number & " " & Err.Source & ": " & Err.Description
        WScript.Quit Err.Number
      end if 
   End Sub
End Class
Dim qeloreObj : Set qeloreObj = New QuitErrorlevelOnRuntimeError

' Do your script work here
' Uncomment this line and run to test that '3' is returned as exit status
'WScript.Quit 3
' Uncomment the below two lines to test that '500' is returned as exit status
'if foofoo then
'end if
' If just one of the above two lines are uncommented, a compile time error '1'
' is returned by cscript itself

Write a comment

New comments have been disabled for this post.