Я пытаюсь загрузить 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
Поскольку вы упоминаете, что ваше приложение является 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. Если они когда-нибудь исправят это, ваше приложение начнет работать правильно, без каких-либо изменений в вашем существующем коде.
В то же время, вы должны быть в состоянии обойти вашу проблему, выполнив это:
%windir%\Sysnative
в какую-то известную папку, которую вы контролируете. (Я предлагаю вам создать папку с уникальным именем внутри %TEMP%
и скопируйте DLL в эту папку). Замечания: Sysnative
это специальный псевдоним, который сопоставляется с системной папкой, System32
под 64-битными выпусками Windows.LoadLibrary()
и передайте ему путь к копии библиотеки DLL, созданной на шаге 1.Описанный выше обходной путь может не работать, если вам требуется поддержка 64-битной Windows XP, так как Sysnative
задокументировано, что псевдоним работает только в Windows Vista или более поздней версии. Альтернативный обходной путь — вручную обойти перенаправление файловой системы:
Wow64DisableWow64FsRedirection()
, Это позволит вашему приложению увидеть, что действительно в System32
,System32
в какую-то известную папку, которую вы контролируете.Wow64RevertWow64FsRedirection()
,LoadLibrary()
и передайте ему путь к копии библиотеки DLL, которую вы сделали на шаге 2.Обратите внимание, что если вы думаете о звонке Wow64DisableWow64FsRedirection()
получить LoadLibrary()
работать без необходимости копировать DLL, не беспокойтесь: LoadLibrary()
не обращает внимания на эту настройку. (Я действительно проверял это.)
Дополнительная информация: Перенаправитель файловой системы
Других решений пока нет …