Поделиться через


Обработка ошибок и предупреждений

Если программа использует библиотеки DLL с задержкой, она должна надежно обрабатывать ошибки, так как ошибки, возникающие во время выполнения программы, приводят к необработанным исключениям. Обработка сбоев состоит из двух частей: восстановления с помощью перехватчика и создания отчетов через исключение.

Дополнительные сведения об обработке ошибок и уведомлениях о задержке загрузки DLL см. в статье "Общие сведения о вспомогательной функции".

Дополнительные сведения о функциях перехватчика см. в разделе "Структура" и "Константные определения".

Восстановление через крючок

Код может потребоваться восстановить при сбое или предоставить альтернативную библиотеку или подпрограмму. Вы можете предоставить перехватчик вспомогательной функции, которая может предоставить альтернативный код или исправить ситуацию. Подпрограмма перехватчика должна возвращать подходящее значение, чтобы обработка может продолжаться (или HINSTANCE FARPROC). Кроме того, он может вернуть значение 0, чтобы указать, что исключение должно быть создано. Он также может выбросить свое собственное исключение или longjmp из крючка. Есть перехватчики уведомлений и перехватчики сбоев. Для обоих может использоваться одна и та же подпрограмма.

Обработчики уведомлений

Перехватчики уведомлений о задержке загрузки вызываются непосредственно перед выполнением следующих действий в вспомогательной процедуре:

  • Сохраненный дескриптор библиотеки проверяется, был ли он загружен.

  • LoadLibrary вызывается для попытки загрузки библиотеки DLL.

  • GetProcAddress вызывается для попытки получить адрес процедуры.

  • Вернитесь к блоку загрузки импорта задержки.

Включен перехватчик уведомлений:

  • Указав новое определение указателя __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 перехватчика вместе со значением уведомления. Эти данные идентичны данным, используемым вспомогательной подпрограммой задержки загрузки. Значение уведомления будет одним из значений, определенных в определениях структуры и констант.

Обработчики сбоев

Перехватчик сбоя включен так же, как и перехватчик уведомлений. Подпрограмма перехватчика должна возвращать подходящее значение, чтобы продолжить обработку (или HINSTANCE FARPROC) или 0, чтобы указать, что исключение должно быть создано.

Переменная указателя, которая ссылается на определяемую пользователем функцию:

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

Структура DelayLoadInfo содержит все соответствующие данные, необходимые для подробных отчетов об ошибке, включая значение из GetLastError.

Если уведомление имеет значение dliFailLoadLib, функция перехватчика может возвращать следующее:

  • 0, если он не может справиться с ошибкой.

  • Если HMODULEперехватчик сбоя исправил проблему и загрузил саму библиотеку.

Если уведомление имеет значение dliFailGetProc, функция перехватчика может возвращать следующее:

  • 0, если он не может справиться с ошибкой.

  • Допустимый адрес proc (адрес функции импорта), если перехватчик сбоя успешно получил сам адрес.

Отчет с помощью исключения

Если все, что необходимо для обработки ошибки, заключается в прерывании процедуры, не требуется перехватчик, если пользовательский код может обрабатывать исключение.

Задержка кодов исключений загрузки

Структурированные коды исключений могут возникать при возникновении сбоев во время отложенной загрузки. Значения исключения задаются с помощью 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 значении, полученном GetExceptionInformation EXCEPTION_RECORD из структуры, в ExceptionInformation[0] поле.

Если в поле заданы grAttrs неправильные биты, создается исключение ERROR_INVALID_PARAMETER . Это исключение является смертельным для всех намерений и целей.

Дополнительные сведения см. в разделе "Структура" и "Константные определения".

См. также

Поддержка компоновщика для dll с задержкой