運行時錯誤處理的元素

此頁沒有內(nèi)容條目
內(nèi)容

expandtri全部顯示

錯誤和錯誤處理

編寫應(yīng)用程序時,必須考慮出現(xiàn)錯誤時應(yīng)該怎么辦。有兩個原因會導(dǎo)致應(yīng)用程序中出錯。第一,在運行應(yīng)用程序時某些條件可能會使原本正確的代碼產(chǎn)生錯誤。例如,如果代碼嘗試打開一個已被用戶刪除的,就會出錯。第二,代碼可能包含不正確的邏輯,導(dǎo)致不能運行所需的操作。例如,如果在代碼中試圖將數(shù)值被 0 除,就會出現(xiàn)錯誤。

如果沒有做任何錯誤處理,則在代碼出錯時 Visual Basic 將停止運行并顯示一條出錯消息。當(dāng)發(fā)生這種情況時,用戶很可能對此感到迷惑和沮喪。通過把完整的錯誤處理例程包含在代碼中來處理可能產(chǎn)生的所有錯誤,可以預(yù)防許多問題。

當(dāng)將錯誤處理代碼添加到過程中時,應(yīng)當(dāng)考慮在出現(xiàn)錯誤時過程將如何控制執(zhí)行順序。在將執(zhí)行交給錯誤處理程序的步驟中,第一步是通過將某些形式的 On Error 語句包含在過程中而啟用錯誤處理程序。On Error 語句在錯誤事件中對執(zhí)行進行定向。如果沒有 On Error 語句,在出現(xiàn)錯誤時 Visual Basic 只是簡單地中止程序執(zhí)行并顯示一條出錯消息。

如果已啟用了錯誤處理程序的過程發(fā)生了錯誤,Visual Basic 將并不顯示普通的出錯消息,而是將它路由給錯誤處理程序(如果存在)。當(dāng)執(zhí)行傳遞到一個已啟用的錯誤處理程序時,該錯誤處理程序就被激活。在活動的錯誤處理程序中,可以確定出現(xiàn)的錯誤類型,并按所選的方式處理它。Microsoft Access 提供了三類對象,它們包含關(guān)于已發(fā)生錯誤的信息。這三類對象分別是:ADO Error 對象、Visual Basic Err 對象和 DAO Error 對象。

出現(xiàn)錯誤時路由執(zhí)行

錯誤處理程序指定發(fā)生錯誤時過程如何響應(yīng)。例如,在出現(xiàn)特定的錯誤時您可能需要終止過程的運行,或者需要改正導(dǎo)致錯誤的條件并恢復(fù)過程執(zhí)行。On ErrorResume 語句決定了如何在錯誤事件中繼續(xù)執(zhí)行。

On Error 語句

On Error 語句啟用或禁用錯誤處理例程。如果啟用了錯誤處理例程,則當(dāng)出現(xiàn)錯誤時執(zhí)行會傳遞給錯誤處理例程。

On Error 語句有三種形式:On Error GoTo label、On Error GoTo 0On Error Resume Next。On Error GoTo label 語句啟用錯誤處理例程,該例程從這個語句出現(xiàn)的代碼行開始執(zhí)行。應(yīng)當(dāng)在可能出現(xiàn)錯誤的第一行代碼前啟用錯誤處理例程。在錯誤處理程序被激活并出現(xiàn)錯誤時,執(zhí)行就會傳到由 label 參數(shù)指定的代碼行上。

由 label 參數(shù)指定的行應(yīng)是錯誤處理例程的開頭。例如,下面的過程指定:如果發(fā)生錯誤,執(zhí)行會傳給標(biāo)簽為 Error_MayCauseAnError 的行:

Function MayCauseAnError()

    ' Enable error handler.

    On Error GoTo Error_MayCauseAnError

    .            ' Include code here that may generate error.

    .

    .

Error_MayCauseAnError:

    .            ' Include code here to handle error.

    .

    .

End Function

On Error GoTo 0 語句在過程中禁用錯誤處理。即使過程中包含有標(biāo)號為 0 的代碼行,該語句也不把 0 行指定為錯誤處理代碼的起始。如果代碼中沒有 On Error GoTo 0 語句,則在過程運行完成時將自動禁用錯誤處理程序。On Error GoTo 0 語句會重置 Err 對象的屬性,這與使用 Err 對象的 Clear 方法效果一樣。

On Error Resume Next 語句會忽略導(dǎo)致錯誤的代碼行并將執(zhí)行路由到錯誤代碼行的下一行。此時過程執(zhí)行并沒有中止。如果要檢查緊挨可能導(dǎo)致錯誤的代碼行之后的 Err 對象的屬性,并且要在過程中(而不是錯誤處理程序中)處理錯誤,則可使用 On Error Resume Next 語句。

Resume 語句

Resume 語句將執(zhí)行從錯誤處理例程中重定向回到過程的主體。如果要從過程某一特定點上繼續(xù)執(zhí)行程序,則可以在錯誤處理例程中包含 Resume 語句。不過 Resume 語句并不是必需的;也可以在運行完錯誤處理例程之后就結(jié)束過程。

Resume 語句有三種形式。其中 ResumeResume 0 語句將執(zhí)行返回到發(fā)生錯誤的代碼行。而 Resume Next 語句將執(zhí)行返回到錯誤代碼行的下一行。Resume label 語句則將執(zhí)行返回到由 label 參數(shù)指定的代碼行。label 參數(shù)必須指定一個行標(biāo)簽或一個行號。

通常如果要求用戶必須更正錯誤,則可以使用 ResumeResume 0 語句。例如,如果提示用戶輸入一個表的名稱以便打開該表,而用戶輸入了一個并不存在的表名,則可以再次提示用戶并在導(dǎo)致錯誤的語句上繼續(xù)程序的執(zhí)行。

如果代碼在錯誤處理程序中改正了錯誤,并且無需再次運行引起錯誤的代碼行而想繼續(xù)執(zhí)行,可以使用 Resume Next 語句。如果想在過程中由 label 參數(shù)指定的其他代碼行上繼續(xù)執(zhí)行,則可以使用 Resume label 語句。例如,可以在退出例程上恢復(fù)程序的運行,如以下章節(jié)所述。

退出過程

在過程中包含一個錯誤處理例程的同時,還應(yīng)該包括一個退出例程,以便只有在發(fā)生錯誤時才運行錯誤處理例程。可以像指定錯誤處理例程一樣用行標(biāo)簽指定退出例程。

例如,可以將退出例程添加到前面章節(jié)的示例中。如果沒有出現(xiàn)錯誤,退出例程在過程主體之后運行。而如果出現(xiàn)錯誤,則在運行完錯誤處理例程之后執(zhí)行將傳到退出例程。退出例程包含一個 Exit 語句。

Function MayCauseAnError()

    ' Enable error handler.

    On Error GoTo Error_MayCauseAnError

    .            ' Include code here that may generate error.

    .

    .

Exit_MayCauseAnError:

    Exit Function

Error_MayCauseAnError:

    .            ' Include code to handle error.

    .

    .

    ' Resume execution with exit routine to exit function.

    Resume Exit_MayCauseAnError

End Function

處理嵌套過程中的錯誤

當(dāng)一個沒有已啟用的錯誤處理程序的嵌套過程中出現(xiàn)錯誤時,Visual Basic 將通過向后搜索調(diào)用列表查找其他過程中已啟用的錯誤處理程序,而不是簡單地中止執(zhí)行程序。這就使得代碼有機會在其他過程中糾正錯誤。例如,假設(shè)過程 A 調(diào)用過程 B,過程 B 調(diào)用過程 C。如果過程 C 出現(xiàn)錯誤而其中沒有已啟用的錯誤處理程序,則 Visual Basic 會先檢查過程 B 再檢查過程 A,以找出已啟用的錯誤處理程序。如果找到了,執(zhí)行就會傳到該錯誤處理程序。否則會中止程序執(zhí)行并顯示出錯消息。

當(dāng)活動的錯誤處理程序中出現(xiàn)錯誤時,Visual Basic 也會通過向后搜索調(diào)用列表查找已啟用的錯誤處理程序。通過用 Err 對象的 Raise 方法在活動的錯誤處理程序中產(chǎn)生錯誤,可以強制 Visual Basic 向后搜索調(diào)用列表。這在處理錯誤處理程序中出現(xiàn)預(yù)料外的錯誤時很有用。如果出現(xiàn)預(yù)料之外的錯誤,而在錯誤處理程序中又重新生成了該錯誤,則執(zhí)行將按照調(diào)用列表的逆序傳遞以查找其他可能被設(shè)置來處理該錯誤的錯誤處理程序。

例如,假設(shè)過程 C 有一個已啟用的錯誤處理程序,但并未糾正已經(jīng)出現(xiàn)的錯誤。當(dāng)該錯誤處理程序檢查了所有預(yù)料之中的錯誤之后,它可以重新產(chǎn)生原有的錯誤。此時執(zhí)行將按照調(diào)用列表的逆序傳給過程 B 中的錯誤處理程序(如果存在該程序的話),給該錯誤處理程序糾正錯誤的機會。如果過程 B 沒有錯誤處理程序或者如果不能糾正錯誤并重新生成了錯誤,則執(zhí)行將傳給過程 A 中的錯誤處理程序(假設(shè)該誤處理程序存在)。

為了換一個角度來闡明這個概念,假設(shè)有一個嵌套過程,其中包含的錯誤處理程序用于處理預(yù)料中類型可能不匹配的錯誤。過程 C 的某個代碼行上出現(xiàn)了一個預(yù)料之外的錯誤:值被 0 除。如果包含了一個重新生成原有錯誤的語句,則執(zhí)行將按照調(diào)用列表的逆序傳給其他已啟用的錯誤處理程序(如果存在該程序的話)。如果已在調(diào)用列表中的另一個過程中糾正了“值被 0 除”的錯誤,那么該錯誤就可被糾正。但如果代碼不重新生成該錯誤,則過程將繼續(xù)運行但不糾正“值被 0 除”的錯誤。按照這種次序有可能會在嵌套過程集內(nèi)產(chǎn)生其他錯誤。

總之,在以下情況下 Visual Basic 會按照調(diào)用列表的逆序搜索已啟用的錯誤處理程序:

?過程中出現(xiàn)錯誤,而該過程又不包含已啟用的錯誤處理程序。
?在活動的錯誤處理程序中出現(xiàn)錯誤。如果使用 Err 對象的 Raise 方法來產(chǎn)生一個錯誤,就可強制 Visual Basic 向后搜索調(diào)用列表以查找已啟用的錯誤處理程序。

獲得有關(guān)錯誤的信息

一旦執(zhí)行傳至錯誤處理例程,代碼就必須確定發(fā)生了何種錯誤并處理它。Visual Basic 和 Microsoft Access 提供了幾種可用來獲取特定錯誤信息的語言元素。每種語言元素都適用于不同類型的錯誤。因為錯誤將發(fā)生在應(yīng)用程序的不同部分,所有需要根據(jù)所預(yù)期的錯誤在代碼中選擇使用不同的語言元素。

可用于錯誤處理的語言元素有:

?Err 對象。
?ADO Error 對象和 Errors 集合。
?DAO Error 對象和 Errors 集合。

?AccessError 方法。

?Error 事件。

Err 對象

Err 對象是由 Visual Basic 提供的。當(dāng)出現(xiàn) Visual Basic 錯誤時,有關(guān)該錯誤的信息將存儲在 Err 對象中。Err 對象每次只維護一個錯誤的信息。當(dāng)出現(xiàn)新的錯誤時,Err 對象將更新為新的錯誤信息。

若要獲取某個特定錯誤的信息,可以使用 Err 對象的屬性和方法。Number 屬性是 Err 對象的默認屬性。它將返回所出現(xiàn)的錯誤的標(biāo)識號。Err 對象的 Description 屬性則返回與 Visual Basic 錯誤有關(guān)的描述性字符串。Clear 方法將清除 Err 對象的當(dāng)前錯誤信息。Raise 方法可生成一個特定的錯誤并用關(guān)于該錯誤的信息填充 Err 對象的屬性。

下面的示例說明了如何在可能導(dǎo)致類型不匹配錯誤的過程中使用 Err 對象:

Function MayCauseAnError()

    ' Declare constant to represent likely error.

    Const conTypeMismatch As Integer = 13

    On Error GoTo Error_MayCauseAnError

        .            ' Include code here that may generate error.

        .

        .

Exit_MayCauseAnError:

    Exit Function

Error_MayCauseAnError:

    ' Check Err object properties.

    If Err = conTypeMismatch Then

        .            ' Include code to handle error.

        .

        .

    Else

        ' Regenerate original error.

        Dim intErrNum As Integer

        intErrNum = Err

        Err.Clear

        Err.Raise intErrNum

    End If

    ' Resume execution with exit routine to exit function.

    Resume Exit_MayCauseAnError

End Function

請注意在上面的示例中,Raise 方法用來重新產(chǎn)生原有的錯誤。如果出現(xiàn)除了類型不匹配以外的錯誤,執(zhí)行將按照調(diào)用列表的逆序傳遞給其他的錯誤處理程序(如果存在該程序的話)。

Err 對象提供了所需有關(guān) Visual Basic 錯誤的所有信息。然而,它并沒有給出有關(guān) Microsoft Access 錯誤或 Microsoft Jet 數(shù)據(jù)庫引擎錯誤的完整信息。Microsoft Access 和數(shù)據(jù)訪問對象 (DAO) 提供了附加的語言元素來幫助處理這些錯誤。

Error 對象和 Errors 集合

Error 對象和 Errors 集合是由 ADO 和 DAO 提供的。Error 對象代表一個 ADO 或 DAO 錯誤。單個 ADO 或 DAO 操作可能引起幾個錯誤,特別是執(zhí)行 DAO ODBC 操作時。在特定數(shù)據(jù)訪問操作過程中發(fā)生的每個錯誤都有一個相關(guān) Error 對象。與特定的 ADO 或 DAO 對象有關(guān)的所有 Error 對象都存儲在 Errors 集合中,其中最低級別的錯誤為集合中的第一個對象,最高級別的錯誤為集合中的最后一個對象。

出現(xiàn) ADO 或 DAO 錯誤時,Visual Basic 的 Err 對象包含 Errors 集合中第一個對象的錯誤編號。若要確定是否出現(xiàn)了其他的 ADO 或 DAO 錯誤,可檢查 Errors 集合。Errors 集合中第一個 Error 對象的 ADO Number 或 DAO Number 屬性和 ADO Description 或 DAO Description 屬性應(yīng)該與 Visual Basic Err 對象的 NumberDescription 屬性值相匹配。

AccessError 方法

使用 Err 對象的 Raise 方法可產(chǎn)生一個實際上并未出現(xiàn)的 Visual Basic 錯誤并確定與該錯誤相關(guān)的描述性字符串。然而,不能使用 Raise 方法產(chǎn)生 Microsoft Access 錯誤、ADO 錯誤或 DAO 錯誤。若要確定與實際上并未發(fā)生的 Microsoft Access 錯誤、ADO 錯誤或 DAO 錯誤相關(guān)的描述性字符串,可使用 AccessError 方法。

Error 事件

使用 Error 事件可捕獲發(fā)生在 Microsoft Access 窗體報表上的錯誤。例如,當(dāng)用戶試圖在數(shù)據(jù)類型為“日期/時間”的字段中輸入文本就會發(fā)生 Error 事件。如果把 Error 事件過程添加到“雇員”窗體上,然后試圖在“雇傭日期”字段中輸入一個文本值,Error 事件過程就會運行。

Error 事件過程有一個整型參數(shù) DataErr。在運行 Error 事件過程時,DataErr 參數(shù)將包含出現(xiàn)的 Microsoft Access 錯誤的編號。確定發(fā)生錯誤的編號的唯一方法就是在事件過程中檢查 DataErr 參數(shù)。在發(fā)生 Error 事件之后,Err 對象并不為錯誤信息所填充??蓪?DataErr 參數(shù)值與 AccessError 方法一起使用來確定錯誤編號及其描述性字符串。

注釋  提供 Error 語句和 Error 函數(shù)的目的只是為了向后兼容。在編寫新代碼時,請使用 ErrError 對象、AccessError 函數(shù)和 Error 事件來獲取錯誤信息。