РЕДАКТИРОВАТЬ : Предварительно (см. Предостережения) предложили это, я быстро начинаю думать, что это очень плохая идея, но я оставляю ее здесь для потомков. Наиболее веская причина не использовать это от Эрика Липперта из Microsoft, который работал над дизайном и реализацией VBScript. Он заявляет, в ответ на другой вопрос : VBScript не дает никаких гарантий, что терминаторы всегда работают . Это может означать, что это иногда не возвращает код выхода, отличный от 0, в случае необработанной ошибки.
Я думаю, что лично я буду использовать «пакетный файл-обертку, который вычитает 1 из кода выхода cscript» в будущем.
Мне нравится решение, связанное с fmunkert, но я думаю, что оно требует, чтобы вы поместили свой код в определенный Class_Initalize, который в лучшем случае неуклюж. Я разработал соответствующее решение, которое не требует этого; вы просто «фиксируете» успешный результат в конце своего кода; если это не вызывается, любое исключение заставляет экземпляр Class_Terminate ExitCodeHandler установить ненулевой код завершения.
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 (Инициализация ресурсов - инициализация)
Вы, конечно, могли бы приукрасить класс так, чтобы он поддерживал другие коды выхода, сообщения об ошибках и т. Д. Вы можете поместить это в общий файл VBS и использовать механизм для включения в VBScript , чтобы поделиться им.
Предостережения
Я не знаю всех подробностей недостатков при вызове WScript.Quit во время разматывания стека из-за исключения в VBScript. Я обнаружил следующее:
- Используйте с осторожностью. Я придумал это и стал возиться с ним, когда увидел связанное предложение Фмункерта, а не использовал его широко.
- Если вы явно вызовете WScript.Quit ( n ), ExitCodeHandler заменит n своим собственным кодом выхода. Обходной путь должен либо всегда вызывать ExitCodeHandler.Commit перед вызовом
WScript.Quit
, либо вместо этого вызывать предоставленный ExitCodeHandler.Quit
, который делает это за вас. Тем не менее, использование любого из этих методов не всегда может быть практичным / возможным, и это довольно не идиоматично и не может быть очевидным для сопровождающих.
- Если любой другой объект с
Class_Terminate
завершается (т. Е. после ExitCodeHandler's Class_Terminate
вызывает WScript.Quit), вы, похоже, получаете сообщение об ошибке. Вы можете получить аналогичное поведение с любыми COM-объектами, которые уничтожаются. Я не знаю, в каком порядке VBScript уничтожает объекты (или даже если это гарантировано), поэтому я спросил об этом в другом вопросе .