Fix any error in VBScript?

I have a batch file that calls a VBScript program (.vbs). After calling it, my batch of script will check %errorlevel% to see if the .vbs program worked. I can report an error with the exit code in the .vbs program using WScript.Quit(1) .

However, I can do it explicitly. If some unexpected error occurs at runtime, .vbs exits with an error dialog box, however the exit code is zero, so my batch file thinks this happened! How can I change this behavior?

And if you want to say, use on error goto , don't worry ... this syntax is available in regular VB, but not in VBScript.

+4
source share
5 answers

I was thinking about a ready-made solution ... Who said 0 should mean success? VBScript sometimes returns a return code of 0 for crashes, so why not accept this? Accept 0 as (at least one possible) failure code and compose another number (for example, 10) as a "success code".

At the end of the script, enter WScript.Quit (10). It will be amazed only if everything is achieved before this point. Then, instead of "if errorlevel 1" in the calling batch file, use "if% errorlevel% == 10"

+4
source

EDIT : presumably (see reservations) suggested this, I quickly start to think that this is a very bad idea, but I leave it here for posterity. The most compelling reason not to use this comes from Eric Lippert at Microsoft, who worked on the design and implementation of VBScript. He claims In response to another question : VBScript does not guarantee that terminators will always run . This may mean that it sometimes does not return an exit code without a code in the event of an unhandled error.

I think that I personally will use the "shell batch file", which subsequently subtracts 1 from the cscript exit code.


I like the fmunkert-related solution, but I think it requires you to put your code in a specific Class_Initalize, which is clumsy at best. I have developed an appropriate solution that does not require this; you simply β€œcomplete” the successful result at the end of your code; if it is not called, any exception throws an instance of ExitCodeHandler Class_Terminate to set a nonzero exit code.

 Option Explicit Class ExitCodeHandler private exit_code Public Sub Commit() exit_code = 0 End Sub Private Sub Class_Initialize() exit_code = -1 ' this exit code will be returned if Commit is never called End Sub Private Sub Class_Terminate() if exit_code<>0 then WScript.Quit(exit_code) End Sub Public Sub Quit(exitCode) Commit WScript.Quit(exitCode) ' exit code will be respected since we have committed End Sub End Class ' create one of these at the start: Dim ech: Set ech = New ExitCodeHandler WSCript.StdOut.WriteLine "Hello" s = "" ' undeclared variable causes runtime error - comment out to see success. ' WScript.Quit(-4) ' before a commit, -1 is returned due to the Class_Terminate ' Commit at the end ech.Commit ' WScript.Quit(-5) ' after a commit, -5 is returned 

Note that this idiom is heavily used in C ++, where it is called RAII (Resource Initialization)

Of course, you could decorate the class to support other exit codes, error messages, etc. You can put this in a shared vbs file and use to include in vbscript to share it.

Warnings

I don’t know the full details of the undersides of a WScript.Quit call during stack expansion due to an exception in VBScript. I disabled the following:

  • Use with caution. I came up with this and stuck with it when I saw fmunkert related to the proposal, did not use it extensively.
  • If you explicitly call WScript.Quit (n), ExitCodeHandler will replace n with its own exit code. The workaround is to either always call ExitCodeHandler.Commit before calling WScript.Quit , or instead use the supplied ExitCodeHandler.Quit , which does this for you. However, relying on any of these methods may not always be practical / possible, and it is rather non-idiomatic and may not be disgusting to those involved.
  • If any other object with Class_Terminate completes (i.e. after ExitCodeHandler Class_Terminate calls WScript.Quit), you seem to get an error. You can get similar behavior with any COM objects that are destroyed. I do not know in what order VBScript destroys objects (or even if they are guaranteed), so I asked about this in another question .
+4
source

As you say, all available On Error Resume Next , so you are forced to use a template:

 On Error Resume Next ThingWithAChanceOfThrowingAnError ... If (Err.number <> 0) then PrintErrorAndQuitWith1(Err.Description) 
+2
source

If this is an option, you can use jscript that better supports exception handling, including a simple way to return a non-zero exit code for any exception. See Solution why does my JScript (Windows script host) go from 0 to an uncaught exception?

This is the # 1 reason we choose jscript over vbscript (when should we use one of the two!)

+2
source

You can use the technique described in this article . This requires you to wrap the script inside the VBScript class.

+1
source

Source: https://habr.com/ru/post/1311212/


All Articles