簡體   English   中英

捕獲VBScript中的任何錯誤?

[英]capture any error in VBScript?

我有一個調用VBScript(.vbs)程序的批處理文件。 調用后,我的批處理腳本檢查%errorlevel%來查看.vbs程序是否失敗。 我可以使用WScript.Quit(1)在.vbs程序中使用退出代碼來發出失敗信號。

但是,我只能明確地做到這一點。 如果發生一些意外的運行時錯誤,.vbs會退出並顯示一個錯誤對話框, 但是退出代碼為零,因此我的批處理文件認為成功了! 我該如何改變這種行為?

而且,如果您想說的話,請on error goto使用,不要打擾...該語法在常規VB中可用,但在VBScript中不可用。

我想到了一個現成的解決方案...誰說0意味着成功? VBScript有時會針對失敗返回0返回碼,那么為什么不接受它呢? 采用0作為(至少一個可能的)失敗代碼,並添加另一個數字(例如10)作為“成功代碼”。

在腳本末尾,放入WScript.Quit(10)。 只有到那時一切都成功了,這才會受到打擊。 然后,使用“ if%errorlevel%== 10”代替調用批處理文件中的“ if errorlevel 1”。

編輯 :試探性地(見警告)提出了這個建議,我迅速開始認為這是一個非常糟糕的主意,但我將其留給后代參考。 不使用此功能的最有說服力的原因來自Microsoft的Eric Lippert ,他從事VBScript的設計和實現。 回答另一個問題時說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(資源獲取是初始化)

當然,您可以修飾該類以支持其他退出代碼,錯誤消息等。您可能希望將其放在通用的vbs文件中,並使用vbscript中包含機制來共享它。

注意事項

我不知道在堆棧展開期間調用WScript.Quit的缺點的全部細節,這是由於VBScript中的異常。 我改變了以下幾點:

  1. 請謹慎使用。 當我看到fmunkert的關聯建議而不是廣泛使用它時,我想出了這個問題並加以探討。
  2. 如果您顯式調用WScript.Quit( n ),則ExitCodeHandler將n替換為其自己的退出代碼。 解決方法是始終在調用WScript.Quit之前先調用ExitCodeHandler.Commit,或者調用提供的ExitCodeHandler.Quit來代替。 但是,依靠這兩種方法中的任何一種可能並不總是可行/可行的,並且這完全是慣用的,對維護者而言也不是一件好事。
  3. 如果具有Class_Terminate任何其他對象被終止(即, ExitCodeHandler的Class_Terminate調用WScript.Quit之后),您似乎會收到錯誤。 您可能會遇到與被銷毀的任何COM對象類似的行為。 我不知道VBScript會以什么順序銷毀對象(或者即使可以保證銷毀對象),因此我在另一個問題中詢問了它

就像您說的那樣,所有可用的內容都是On Error Resume Next ,因此您不得不使用該模式:

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

如果可以的話,可以使用jscript代替,它對異常處理有更好的支持,包括一種在任何異常上返回非零退出代碼的簡便方法。 請參閱解決方案, 為什么在未捕獲的異常中我的JScript(Windows腳本宿主)以0退出?

這是我們選擇jscript而不是vbscript的#1原因(當我們必須使用兩者之一時!)

您可能會使用本文中介紹的技術。 它要求您將腳本包裝在VBScript類中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM