Gestione e notifica degli errori

Se il programma usa DLL caricate in ritardo, deve gestire gli errori in modo affidabile, poiché gli errori che si verificano durante l'esecuzione del programma genereranno eccezioni non gestite. La gestione degli errori è costituita da due parti: ripristino tramite un hook e segnalazione tramite un'eccezione.

Per altre informazioni sulla gestione e la notifica degli errori di caricamento ritardato della DLL, vedere Informazioni sulla funzione helper.

Per altre informazioni sulle funzioni hook, vedere Struttura e definizioni costanti.

Ripristino tramite un hook

Il codice potrebbe dover eseguire il ripristino in caso di errore o per fornire una libreria o una routine alternativa. È possibile fornire un hook alla funzione helper che può fornire il codice alternativo o risolvere la situazione. La routine hook deve restituire un valore appropriato, in modo che l'elaborazione possa continuare (o HINSTANCEFARPROC). In alternativa, può restituire 0 per indicare che deve essere generata un'eccezione. Potrebbe anche generare la propria eccezione o longjmp uscire dall'hook. Sono disponibili hook di notifica e hook di errore. La stessa routine può essere utilizzata per entrambi.

Hook di notifica

Gli hook di notifica di caricamento ritardato vengono chiamati subito prima che vengano eseguite le azioni seguenti nella routine helper:

  • L'handle archiviato nella libreria viene controllato per verificare se è già stato caricato.

  • LoadLibrary viene chiamato per tentare il caricamento della DLL.

  • GetProcAddress viene chiamato per tentare di ottenere l'indirizzo della routine.

  • Tornare al caricamento di caricamento ritardato del caricamento.

L'hook di notifica è abilitato:

  • Specificando una nuova definizione del puntatore __pfnDliNotifyHook2 inizializzato per puntare alla propria funzione che riceve le notifiche.

    -oppure-

  • Impostando il puntatore __pfnDliNotifyHook2 sulla funzione hook prima di qualsiasi chiamata alla DLL che il programma ritarda il caricamento.

Se la notifica è dliStartProcessing, la funzione hook può restituire:

  • NULL

    L'helper predefinito gestisce il caricamento della DLL. È utile chiamare solo a scopo informativo.

  • puntatore a funzione

    Ignorare la gestione predefinita del caricamento ritardato. Consente di fornire un gestore di carico personalizzato.

Se la notifica è dliNotePreLoadLibrary, la funzione hook può restituire:

  • 0, se vuole solo notifiche informative.

  • Oggetto HMODULE per la DLL caricata, se ha caricato la DLL stessa.

Se la notifica è dliNotePreGetProcAddress, la funzione hook può restituire:

  • 0, se vuole solo notifiche informative.

  • Indirizzo della funzione importata, se la funzione hook ottiene l'indirizzo stesso.

Se la notifica è dliNoteEndProcessing, il valore restituito della funzione hook viene ignorato.

Se questo puntatore viene inizializzato (diverso da zero), l'helper di caricamento ritardato richiama la funzione in determinati punti di notifica durante l'esecuzione. Il puntatore di funzione ha la definizione seguente:

// 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;

Le notifiche passano una DelayLoadInfo struttura alla funzione hook insieme al valore di notifica. Questi dati sono identici ai dati usati dalla routine helper di caricamento ritardato. Il valore di notifica sarà uno dei valori definiti in Struttura e definizioni costanti.

Hook di errore

L'hook di errore è abilitato nello stesso modo dell'hook di notifica. La routine hook deve restituire un valore appropriato in modo che l'elaborazione possa continuare (o HINSTANCEFARPROC) o 0 per indicare che deve essere generata un'eccezione.

La variabile puntatore che fa riferimento alla funzione definita dall'utente è:

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

La DelayLoadInfo struttura contiene tutti i dati pertinenti necessari per la segnalazione dettagliata dell'errore, incluso il valore di GetLastError.

Se la notifica è dliFailLoadLib, la funzione hook può restituire:

  • 0, se non riesce a gestire l'errore.

  • Oggetto HMODULE, se l'hook di errore ha risolto il problema e caricato la libreria stessa.

Se la notifica è dliFailGetProc, la funzione hook può restituire:

  • 0, se non riesce a gestire l'errore.

  • Indirizzo di processo valido (indirizzo della funzione di importazione), se l'hook di errore ha avuto esito positivo nel recupero dell'indirizzo stesso.

Creare report usando un'eccezione

Se tutto ciò che è necessario per gestire l'errore consiste nell'interrompere la procedura, non è necessario alcun hook, purché il codice utente possa gestire l'eccezione.

Codici eccezione di caricamento ritardato

I codici di eccezione strutturati possono essere generati quando si verificano errori durante un caricamento ritardato. I valori delle eccezioni vengono specificati utilizzando una VcppException macro:

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

Per un LoadLibrary errore, viene generato lo standard VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) . Per un GetProcAddress errore, l'errore generato è VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND). L'eccezione passa un puntatore a una DelayLoadInfo struttura. Si trova nel LPDWORD valore recuperato dalla GetExceptionInformationEXCEPTION_RECORD struttura, nel ExceptionInformation[0] campo .

Se nel campo vengono impostati grAttrs bit non corretti, viene generata l'eccezione ERROR_INVALID_PARAMETER . Questa eccezione è, per tutte le finalità e gli scopi, irreversibile.

Per altre informazioni, vedere Struttura e definizioni costanti.

Vedi anche

Supporto del linker per DLL caricate in ritardo