我有一个调用VBScript(.vbs)程序的批处理文件。调用它之后,我的批处理脚本检查%errorlevel%
以查看.vbs程序是否失败。我可以使用WScript.Quit(1)
在.vbs程序中使用退出代码来表示失败。
但是,我只能明确地这样做。如果发生了一些意外的运行时错误,.vbs将退出并显示一个错误对话框,但是退出代码为零,因此我的批处理文件认为它已经超过了!我该如何改变这种行为?
如果你想说,请使用on error goto
,不要打扰......普通VB中的语法可用,但VBScript中没有。
答案 0 :(得分:5)
我想到了一个开箱即用的解决方案......谁说0必须意味着成功? VBScript有时会为失败返回0返回码,那么为什么不接受呢?采用0作为(至少一个可能的)故障代码并组成另一个数字(例如10)作为“成功代码”。
在脚本结束时,输入WScript.Quit(10)。只有在一切顺利到达那一点时才会被击中。然后,而不是调用批处理文件中的“if errorlevel 1”,使用“if%errorlevel%== 10”
答案 1 :(得分:4)
编辑:暂时(见警告)提出这个问题,我很快就开始认为这是一个非常糟糕的主意,但我把它留给了后代。不使用此功能的最令人信服的理由来自微软的 Eric Lippert ,他致力于设计与开发。 VBScript的实现。他说,in answer to another question: VBScript不保证终结者总是运行。这可能意味着在未处理错误的情况下,这有时不会返回非0退出代码。
我想我个人将来会使用一个“从cscript退出代码中减去1的封装批处理文件”。
我喜欢fmunkert链接的解决方案,但我认为它需要您将代码放在特定的Class_Initalize中,这最多是笨拙的。我设计了一个不需要这个的相关解决方案;您只需在代码末尾“提交”成功的结果;如果未调用,则任何异常都会导致ExitCodeHandler的Class_Terminate实例设置非零退出代码。
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
请注意,这个习惯用法在C ++中被大量使用,它被称为RAII (Resource Acquisition Is Initialization)
你当然可以修改这个类以支持其他退出代码,错误消息等。你可能想把它放在一个普通的vbs文件中并使用mechanism for includes in vbscript来共享它。
由于VBScript中的异常,我不知道在堆栈展开期间调用WScript.Quit的缺点的全部细节。我发现了以下内容:
WScript.Quit
之前始终调用ExitCodeHandler.Commit,或者调用提供的ExitCodeHandler.Quit
而不是为您执行此操作。但是,依赖这两种方法中的任何一种方法可能并不总是实用/可行,而且它是非常惯用的,可能不会对维护者产生负面影响。Class_Terminate
的对象被终止(即在 ExitCodeHandler的Class_Terminate
之后调用WScript.Quit),您似乎会收到错误。您可能会遇到与正在销毁的任何COM对象类似的行为。我不知道VBScript以什么顺序销毁对象(或者即使它是有保证的),所以I've asked about it in another question。答案 2 :(得分:2)
正如你所说,所有可用的都是On Error Resume Next
,所以你被迫使用这种模式:
On Error Resume Next
ThingWithAChanceOfThrowingAnError ...
If (Err.number <> 0) then PrintErrorAndQuitWith1(Err.Description)
答案 3 :(得分:2)
如果是一个选项,你可以使用jscript代替它,它更好地支持异常处理,包括在任何异常上返回非零退出代码的简单方法。请参阅why does my JScript (windows script host) exit with 0 on an uncaught exception?
的解决方案这是我们选择jscript而不是vbscript的首要原因(当我们 使用其中一个时!)
答案 4 :(得分:1)
您可以使用this article中描述的技术。 它要求您将脚本包装在VBScript类中。