分享方式:


錯誤處理和通知

如果您的程式使用延遲載入 DLL,它必須健全地處理錯誤,因為程式執行時發生的失敗會導致未處理的例外狀況。 失敗處理是由兩個部分所組成:透過勾點復原,並透過例外狀況報告。

如需 DLL 延遲載入錯誤處理和通知的詳細資訊,請參閱 瞭解協助程式函式

如需攔截函式的詳細資訊,請參閱 結構和常數定義

透過勾點復原

您的程式代碼可能需要在失敗時復原,或提供替代的連結庫或例程。 您可以提供可提供替代程式碼的協助程式函式勾點,或補救情況。 攔截例程需要傳回適當的值,以便處理可以繼續 ( HINSTANCEFARPROC)。 或者,它可以傳回 0,表示應該擲回例外狀況。 它也可以擲回自己的例外狀況或 longjmp 脫離鉤子。 有通知攔截和失敗攔截。 相同的例程可用於兩者。

通知攔截

在協助程式例程中採取下列動作之前,會呼叫延遲載入通知攔截:

  • 已檢查連結庫的預存句柄,以查看它是否已載入。

  • LoadLibrary 呼叫 以嘗試載入 DLL。

  • GetProcAddress 呼叫 以嘗試取得程序的位址。

  • 返回延遲匯入載入 Thunk。

通知攔截已啟用:

  • 藉由提供初始化的新指標 __pfnDliNotifyHook2 定義,以指向接收通知的您自己的函式。

    -或-

  • 將指標 __pfnDliNotifyHook2 設定為攔截函式,再呼叫程式延遲載入的 DLL。

如果通知是 dliStartProcessing,攔截函式可以傳回:

  • NULL

    默認協助程式會處理 DLL 的載入。 僅針對資訊用途呼叫會很有用。

  • 函式指標

    略過默認延遲載入處理。 它可讓您提供自己的載入處理程式。

如果通知是 dliNotePreLoadLibrary,攔截函式可以傳回:

  • 0,如果它只是想要參考通知。

  • HMODULE如果載入 DLL 本身,則為載入 DLL 的 。

如果通知是 dliNotePreGetProcAddress,攔截函式可以傳回:

  • 0,如果它只是想要參考通知。

  • 如果攔截函式取得位址本身,則匯入函式的位址。

如果通知為 dliNoteEndProcessing,則會忽略攔截函式的傳回值。

如果初始化此指標(非零),延遲載入協助程式會在執行期間在特定通知點叫用函式。 函式指標具有下列定義:

// The "notify hook" gets called for every call to the
// delay load helper.  This allows a user to hook every call and
// skip the delay load helper entirely.
//
// dliNotify == {
//  dliStartProcessing |
//  dliNotePreLoadLibrary  |
//  dliNotePreGetProc |
//  dliNoteEndProcessing}
//  on this call.
//
ExternC
PfnDliHook   __pfnDliNotifyHook2;

// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook   __pfnDliFailureHook2;

通知會將 結構傳入 DelayLoadInfo 連結函式,以及通知值。 此數據與延遲載入協助程式例程所使用的數據相同。 通知值將是 Structure 和常數定義定義的其中一個值。

失敗攔截

失敗攔截的啟用方式與 通知攔截相同。 攔截例程必須傳回適當的值,以便處理可以繼續 ( HINSTANCEFARPROC),或 0 表示應該擲回例外狀況。

參考使用者定義函式的指標變數為:

// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook   __pfnDliFailureHook2;

結構 DelayLoadInfo 包含錯誤詳細報告所需的所有相關數據,包括 來自 GetLastError的值。

如果通知是 dliFailLoadLib,攔截函式可以傳回:

  • 0,如果無法處理失敗則為 。

  • 如果 HMODULE失敗勾點已修正問題並載入連結庫本身,則為 。

如果通知是 dliFailGetProc,攔截函式可以傳回:

  • 0,如果無法處理失敗則為 。

  • 如果失敗攔截成功取得位址本身,則為有效的程式位址 (import 函式位址)。

使用例外狀況報告

如果處理錯誤所需的所有專案都是中止程式,只要用戶程式代碼可以處理例外狀況,就不需要攔截。

延遲載入例外狀況代碼

在延遲載入期間發生失敗時,可以引發結構化例外狀況代碼。 例外狀況值是使用 VcppException 巨集來指定:

//
// Exception information
//
#define FACILITY_VISUALCPP  ((LONG)0x6d)
#define VcppException(sev,err)  ((sev) | (FACILITY_VISUALCPP<<16) | err)

若發生 LoadLibrary 失敗,則會擲回標準 VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)GetProcAddress針對失敗,擲回的錯誤為 VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)。 例外狀況會將指標傳遞至 DelayLoadInfo 結構。 其位於 LPDWORD 欄位中,從 EXCEPTION_RECORD 結構擷取GetExceptionInformation的值ExceptionInformation[0]中。

如果欄位中設定 grAttrs 了不正確的位,則會擲回例外狀況 ERROR_INVALID_PARAMETER 。 此例外狀況適用於所有意圖和用途,都是致命的。

如需詳細資訊,請參閱 結構和常數定義

另請參閱

延遲載入 DLL 的連結器支援