LoadLibraryW () не удалось загрузить DLL в System32

Я пытаюсь загрузить DLL, которая была установлена ​​с драйвером принтера, в папку C: \ Windows \ System32 \ с помощью следующего кода:

LoadLibraryW(L"C:\\Windows\\System32\\MagAPI.dll");

GetLastError() сообщает, что «указанный модуль не найден». Если я переместу DLL-библиотеку за пределы папки System32 (например, C: \ SomeFolder \ MagAPI.dll), она загрузится нормально, поэтому не похоже, что это проблема самой DLL. Есть ли какая-то странная функция безопасности Windows, которая может блокировать загрузку моего приложения? Это единственное, о чем я могу думать, но не могу найти однозначных ответов.

Вот отладочный вывод ShowSnaps, который показывает, где он терпит неудачу:

1a8c:1fd4 @ 19006756 - LdrLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - INFO: Loading DLL C:\Windows\system32\MagAPI.dll from path C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpSearchPath - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - ENTER: DLL name: C:\Windows\system32\MagAPI.dll
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpSearchPath - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpLoadDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrLoadDll - RETURN: Status: 0xc0000135

2

Решение

Поскольку вы упоминаете, что ваше приложение является 32-разрядным, загружаемая DLL также должна быть 32-разрядной.

Вероятная причина LoadLibrary() сбой в том, что вы используете 64-разрядную версию Windows, но ваш драйвер принтера ошибочно установил свою 32-разрядную библиотеку DLL в System32 папка вместо SysWOW64 папка.

Немного предыстории: в 64-разрядных выпусках Windows 64-разрядные библиотеки DLL входят в System32 папку, и 32-разрядные библиотеки DLL идут в SysWOW64 папка. Я знаю, это звучит так, как будто все должно быть наоборот, но не позволяйте именам сбивать вас с толку; Папки названы так для обратной совместимости. SysWOW64 папка должна быть прозрачной для приложений: в Windows есть функция, называемая перенаправление файловой системы, которая позволяет 32-разрядным приложениям загружать 32-разрядные библиотеки DLL путем указания System32 папка (как и всегда), даже если библиотеки DLL внутри SysWOW64,

С другой стороны, LoadLibrary() просто откажется загружать DLL, которая была помещена в неправильную папку. Такое поведение вы, вероятно, видите.

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

В то же время, вы должны быть в состоянии обойти вашу проблему, выполнив это:

  1. Прежде чем пытаться загрузить DLL, скопируйте ее из %windir%\Sysnative в какую-то известную папку, которую вы контролируете. (Я предлагаю вам создать папку с уникальным именем внутри %TEMP% и скопируйте DLL в эту папку). Замечания: Sysnative это специальный псевдоним, который сопоставляется с системной папкой, System32 под 64-битными выпусками Windows.
  2. Вызов LoadLibrary() и передайте ему путь к копии библиотеки DLL, созданной на шаге 1.
  3. Когда вы закончите использовать DLL, выгрузите ее и удалите копию, сделанную на шаге 1.

Описанный выше обходной путь может не работать, если вам требуется поддержка 64-битной Windows XP, так как Sysnative задокументировано, что псевдоним работает только в Windows Vista или более поздней версии. Альтернативный обходной путь — вручную обойти перенаправление файловой системы:

  1. Временно отключите перенаправление файловой системы, вызвав Wow64DisableWow64FsRedirection(), Это позволит вашему приложению увидеть, что действительно в System32,
  2. Скопируйте DLL из System32 в какую-то известную папку, которую вы контролируете.
  3. Включите перенаправление файловой системы, вызвав Wow64RevertWow64FsRedirection(),
  4. Вызов LoadLibrary() и передайте ему путь к копии библиотеки DLL, которую вы сделали на шаге 2.
  5. Когда вы закончите использовать DLL, выгрузите ее и удалите копию, сделанную на шаге 2.

Обратите внимание, что если вы думаете о звонке Wow64DisableWow64FsRedirection() получить LoadLibrary() работать без необходимости копировать DLL, не беспокойтесь: LoadLibrary() не обращает внимания на эту настройку. (Я действительно проверял это.)

Дополнительная информация: Перенаправитель файловой системы

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]