- 比较正确和错误实现的速度是没有意义的。如果您的脚本在没有错误处理的情况下无法满足其规范,并且在使用 OERN 时速度变慢,则您必须选择另一种语言。
- 由于 OERN 隐藏错误,其范围应尽可能小。您的示例代码闻起来像在全球范围内使用 OERN - 这是一个非常糟糕的主意。另外:每次有风险的操作和对应的 Err.Number 检查后,都需要 Err.Clear 或“On Error GoTo 0”。
- 在其他语言中(例如 Python)"it's easier to ask forgiveness than permission";由于 VBScript 错误处理的糟糕性质,在大多数情况下,您应该“三思而后行”,并且仅在绝对不可避免时才使用 OERN(例如,检查注册表项是否存在,处理可能出现故障的外部资源)。
本地错误处理的成语:
Dim gaErr ' global error array
...
Sub SomeSub()
...
OERN
risky op
gaErr = Array(Err.Number, Err.Description, ...)
OEG0
If gaErr(0) Then
handle error
...
End Sub
如果您的规范要求进行全局错误处理:
Dim gaErr
OERN
ret = main()
gaErr = Array(...)
OEG0
If gaErr(0) Then
some fatal/not locally handled error occured somewhere in your script
handle it gracefully
Else
If ret is bad Then
deal with this
Else
ask for more money
End If
End If
WScript.Quit good/bad
Function main()
main = ...
End Function
更新评论:
为什么全球 OERN 是邪恶的?考虑:
OERN
(1) Process/change important data
(2) Delete original data - if (1) failed you just destroyed the base of your business
OERN
(1) Process/change important data
(2) If Err.Nunber Then Backup(database, destinatiom)
(3) Continue although the Backup didn't take place, because at least three error were hidden
顺便说一句:您添加 Err.Clear 的位置有误 - 您在可以处理错误之前丢失了错误信息。
更新评论 II:
考虑这个演示脚本:
' dgeh.vbs - demo global error handling
Option Explicit
' globals
Dim gWAN : Set gWAN = WScript.Arguments.Named
Dim gaErr
Dim iRet
' top-level/global OERN starts here (errors before will abort mercylessly)
On Error Resume Next
iRet = main() ' not more than two statements!
gaErr = Array(Err.Number, Err.Description, Err.Source)
On Error GoTo 0
If gaErr(0) Then
WScript.Echo "Fatal Error:", Join(gaErr, " * ")
iRet = 1 ' or choose a better number
Else
If iRet Then
WScript.Echo "need one of /good, /bad, or /fatal, Mr. User!"
Else
WScript.Echo "all's well"
End If
End If
WScript.Quit iRet
Function main()
main = 2
If gWAN.Count = 1 And (gWAN.Exists("good") Or gWAN.Exists("bad") Or gWAN.Exists("fatal")) Then
readTheDocs
main = 0
End If
End Function
Sub readTheDocs()
WScript.Echo "read Microsoft's Docs"
If gWAN.Exists("fatal") Then
caTastrophy
Else
trySomethingRisky
End If
End Sub
Sub trySomethingRisky()
Dim n
If gWAN.Exists("bad") Then n = 1 / 0
WScript.Echo "but be skeptical of the text and your interpretation"
End Sub
Sub caTastrophy()
On Error Resume Next ' simulating the evil global OERN and not checking *each* statement
WScript.Echo "saving the world"
saveTheWorld
WScript.Echo "deleting the now obsolete original"
On Error GoTo 0
End Sub
输出
cscript dgeh.vbs /fatal
read Microsoft's Docs
saving the world
deleting the now obsolete original
all's well
echo %ERRORLEVEL%
0
由于没有 Sub saveTheWorld,您只是将错误处理、VBScript 和所有其他内容都过时了。你甚至不能保证永远不再使用邪恶的全局 OERN,因为你——以及那些习惯性地使用它的脚本编写人员(从而证明他们是为他们的笑话而不是他们的代码获得报酬的)——已经消失了。让我们希望调用过程不会将 ERRORLEVEL 值作为进一步删除的许可。
输出
cscript dgeh.vbs
need one of /good, /bad, or /fatal, Mr. User!
echo %ERRORLEVEL%
2
cscript dgeh.vbs /nix
need one of /good, /bad, or /fatal, Mr. User!
cscript dgeh.vbs /fatal /bad
need one of /good, /bad, or /fatal, Mr. User!
展示“先看再跳”策略。
良好案例的输出:
cscript dgeh.vbs /good
read Microsoft's Docs
but be skeptical of the text and your interpretation
all's well
echo %ERRORLEVEL%
0
两条消息都显示了(理所当然)。
现在完全不同了:
cscript dgeh.vbs /bad
read Microsoft's Docs
Fatal Error: 11 * Division by zero * Microsoft VBScript runtime error
echo %ERRORLEVEL%
1
请标记第二条消息的缺失。除以零将导致在活动 OERN 范围内执行下一行(保存在 gaErr 中)并且 not 继续盲目/盲目地。然后检查有风险的操作(执行 main() 及其所有子项所做的操作)(通过 gaErr 代理)。这符合“在 OERN 范围内不超过两行(风险操作和保存错误信息)”的规则。
为这种全局错误处理付出的代价:您丢失了行号信息 - 优雅地处理错误变得更加困难。
但是由于您的脚本中只有一个 OERN(从现在开始您的程序中不会有 Sub caTastrophy()),您可以在开发和调试期间将其注释掉。
注释掉 OERN 的输出:
cscript dgeh.vbs /bad
read Microsoft's Docs
E:\trials\SoTrials\answers\21901890\vbs\dgeh.vbs(46, 30) Microsoft VBScript runtime error: Division by zero