Skip navigation.

Prepare!

Lee Harvey's Zombie Hit Parade

Posts tagged with "oop"

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.

Try..Catch..Finally in ... VBScript? Sure!

, , , ...

I've been working a lot with VBScript and Windows Scripting Host (WSH) lately. Unfortunately, as many of you VBScript writers know, the error-handling capabilities of VBScript leave a lot to be desired. Luckily, a simple design coding pattern from modern programming languages has revealed a rather unique technique in VBScript that resembles...well, a Try..Catch..Finally block! Yep, you heard correctly. With a liberal dose of multi-line colons ( : ), your VBScript code can attain near perfect Try..Catch..Finally functionality. Note: Guaranteed error-handling, and guaranteed finally block execution in a pseudo-subroutine fashion -- all without requiring an "On Error" statement!

Too good to be true? Here's the catch (no pun intended): You leverage the object lifespan provided by VBScript objects. VBScript supports OOP? Yes sir! Grab a copy of your favorite VBScript documentation, and do a search for "Class".

Basically, here's some pseudo-code that illustrates what we all wish VBScript supported...(yeah, I know VB.NET supports this, bah!)

Sub Func1
   Try
      DoLog "Starting"
      Dim i : i = 65535 ^ 65535 
      MsgBox "Should not see this"
   Catch e
      Select Case e.Number
         Case 6 DoLog "Overflow handled!"
         Case Else DoLog "Unhandled error " & e.Number & " occurred."
      End Select
   Finally
      DoLog "Exiting"
   End Try
End Sub
Call Func1

And here's a reality check...

Class CFunc1
   Private Sub Class_Initialize
      DoLog "Starting"
      Dim i : i = 65535 ^ 65535 
      MsgBox "Should not see this"
   End Sub : Private Sub CatchErr : If Err.Number = 0 Then Exit Sub
      Select Case Err.Number
         Case 6 DoLog "Overflow handled!" 
         Case Else DoLog "Unhandled error " & Err.Number & " occurred."
      End Select
   Err.Clear : End Sub : Private Sub Class_Terminate : CatchErr
      DoLog "Exiting" 
   End Sub 
End Class
Dim Func1 : Set Func1 = New CFunc1 : Set Func1 = Nothing

See a resemblance between the two examples? Sure. And guess what? While the first example doesn't work in VBScript, the second example runs just fine in VBScript 5.6 -- once the DoLog subrountine is defined :smile:

So explain, how does it work? Simple, really. You are defining a Class rather than a Sub-routine. Instantiated Classes (called objects) have a predefined lifespan: a constructor is guaranteed to run once the object is created; and a destructor is guaranteed to run once the object is destroyed. You simply leverage these innate object abilities to handle errors gracefully -- all without using "On Error" statements!

I hope you find this exercise fun, if not useful. I've been rewriting some larger WSH VBScripts using this new technique, and so far so good. I've thrown some various crash scenerios (from the past) at them, and not only did they manage to gracefully handle the errors, but the scripts completely finished without dying mid-way through them -- like they used to.

Enjoy.