Compartir a través de


Notificación y control de errores

Si el programa usa archivos DLL cargados con retraso, debe controlar los errores de forma sólida, ya que los errores que se producen mientras se ejecuta el programa producirán excepciones no controladas. El control de errores se compone de dos partes: recuperación a través de un enlace e informes a través de una excepción.

Para obtener más información sobre el control y la notificación de errores de carga retrasada de DLL, consulte Descripción de la función auxiliar.

Para obtener más información sobre las funciones de enlace, vea Definiciones de estructura y constantes.

Recuperación a través de un enlace

Es posible que el código tenga que recuperarse en caso de error o para proporcionar una biblioteca o rutina alternativa. Puede proporcionar un enlace a la función auxiliar que puede proporcionar el código alternativo o solucionar la situación. La rutina de enlace debe devolver un valor adecuado para que el procesamiento pueda continuar (HINSTANCE o FARPROC). O bien, puede devolver 0 para indicar que se debe producir una excepción. También podría producir su propia excepción o longjmp fuera del enlace. Hay enlaces de notificación y enlaces de error. Se puede usar la misma rutina para ambos.

Enlaces de notificación

Se llama a los enlaces de notificación de carga de retraso justo antes de que se realicen las siguientes acciones en la rutina del asistente:

  • El identificador almacenado en la biblioteca se comprueba para ver si ya se ha cargado.

  • LoadLibrary se llama a para intentar la carga del archivo DLL.

  • GetProcAddress se llama a para intentar obtener la dirección del procedimiento.

  • Vuelva al código de carga de importación de retraso.

El enlace de notificación está habilitado:

  • Al proporcionar una nueva definición del puntero __pfnDliNotifyHook2 que se inicializa para que apunte a su propia función que recibe las notificaciones.

    o bien

  • Al establecer el puntero __pfnDliNotifyHook2 a la función de enlace antes de cualquier llamada al archivo DLL que el programa está retrasando la carga.

Si la notificación es dliStartProcessing, la función de enlace puede devolver:

  • NULL

    El asistente predeterminado controla la carga del archivo DLL. Es útil llamar a solo con fines informativos.

  • Puntero de función.

    Omita el control de carga de retraso predeterminado. Le permite suministrar su propio controlador de carga.

Si la notificación es dliNotePreLoadLibrary, la función de enlace puede devolver:

  • 0, si solo quiere notificaciones informativas.

  • HMODULE para el archivo DLL cargado, si cargó el propio archivo DLL.

Si la notificación es dliNotePreGetProcAddress, la función de enlace puede devolver:

  • 0, si solo quiere notificaciones informativas.

  • La dirección de la función importada, si la función de enlace obtiene la propia dirección.

Si la notificación es dliNoteEndProcessing, se omite el valor devuelto de la función de enlace.

Si este puntero se inicializa (distinto de cero), el asistente de carga retrasada invoca la función en determinados puntos de notificación a lo largo de su ejecución. El puntero de función tiene la siguiente definición:

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

Las notificaciones pasan una estructura DelayLoadInfo a la función de enlace junto con el valor de notificación. Estos datos son idénticos a los datos utilizados por la rutina auxiliar de carga retrasada. El valor de notificación será uno de los valores definidos en Estructura y definiciones de constantes.

Enlaces de error

El enlace de error está habilitado de la misma manera que el enlace de notificación. La rutina de enlace debe devolver un valor adecuado para que el procesamiento pueda continuar (HINSTANCE o FARPROC) o 0 para indicar que se debe iniciar una excepción.

La variable de puntero que hace referencia a la función definida por el usuario es:

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

La estructura DelayLoadInfo contiene todos los datos pertinentes necesarios para la notificación detallada del error, incluido el valor de GetLastError.

Si la notificación es dliFailLoadLib, la función de enlace puede devolver:

  • 0, si no puede controlar el error.

  • HMODULE, si el enlace de error corrigió el problema y cargó la propia biblioteca.

Si la notificación es dliFailGetProc, la función de enlace puede devolver:

  • 0, si no puede controlar el error.

  • Una dirección de procedimiento válida (dirección de función de importación), si el enlace de error se realizó correctamente para obtener la propia dirección.

Informe mediante una excepción

Si todo lo necesario para controlar el error es anular el procedimiento, no es necesario ningún enlace, siempre y cuando el código de usuario pueda controlar la excepción.

Retrasar códigos de excepción de carga

Los códigos de excepción estructurados se pueden generar cuando se producen errores durante una carga retrasada. Los valores de excepción se especifican mediante una macro VcppException:

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

Para un error LoadLibrary, se produce el estándar VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND). Para un error GetProcAddress, el error producido es VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND). La excepción pasa un puntero a una estructura DelayLoadInfo. Está en el valor LPDWORD recuperado por GetExceptionInformation de la estructura EXCEPTION_RECORD, en el campo ExceptionInformation[0].

Si los bits incorrectos se establecen en el campo grAttrs, se produce la excepción ERROR_INVALID_PARAMETER. Esta excepción es, para todas las intenciones y propósitos, irrecuperables.

Para obtener más información, vea Definiciones de estructura y constantes.

Consulte también

Compatibilidad del vinculador con archivos DLL cargados con retraso