Loadlibrary не загружает dll

Обновлено: 06.07.2024

'> Как узнать откуда LoadLibrary неудачно пытался загрузить DLL ?

В своём win32-приложении хочу использовать некую стороннюю но широкоизвестную DLL. Винда 64-битная…

Итог - ошибка 193 (0xC1) ERROR_BAD_EXE_FORMAT - «%1 is not a valid Win32 application.»

Но как мне в своей программе узнать где лежит эта 64-битная DLL которая вызвала ошибку в LoadLibrary() .
Если LoadLibrary() загрузил нормальную 32-битную DLL - то её файл можно найти через GetModuleFileName(). А если DLL не загрузилась - то как искать?

PS. причём в Program Files валяется и несколько 32-битных версий этой DLL, но LoadLibrary до них не доходит натыкаясь на 64-битную версию.

PS. причём в Program Files валяется и несколько 32-битных версий этой DLL, но LoadLibrary до них не доходит натыкаясь на 64-битную версию.
Тогда получается, что главная задача - обнаружить "правильную" dll
и использовать её.
Если сразу не удалось загрузить dll, тогда
можно просто устроить поиск файлов в конкретных директориях.
И попробовать все найденные варианты, используя полные пути.



Может тогда лучше юзать LoadLibraryEx ??
Обрати внимание на третий параметр этой функции.

А что именно?
Я там пробовал DONT_RESOLVE_DLL_REFERENCES сделать (надеялся тогда система не поймёт что это win64-файл, я посмотрю путь, а потом уже вручную сделаю DllMainEntry) - но это не сработало, такая же ошибка ERROR_BAD_EXE_FORMAT сразу.

Варианты ограничивать поиск не подходят, цель именно узнать на какой DLL возникла проблема.



Варианты ограничивать поиск не подходят, цель именно узнать на какой DLL возникла проблема.

Почему не подходят? Что тебе мешает сделать то, что делает функция LoadLibrary? Она ищет в системных директориях подходящие библиотеки. Ты можешь ей это запретить, и сам поискать в этих дерикториях. На какой упадет с нужным тебе результатом, тот и выдавай.

Добавлено 01.02.20, 20:18
Напихать в массив стрингов системные директории, и потом в цикле просто идти по ним, формировать нужный путь к файлу, пытаться загружать - ловить ошибку. Анализировать ошибку. Выдавать результат. Не вижу проблемы. Ты ее сам выдумал.

второй и все последующие разы:
причем это на машинах с клиентом Оракла 11 (Win7 и Win2003ts)
на машинах c другими клиентами не проявляется

Posted via ActualForum NNTP Server 1.5

Posted via ActualForum NNTP Server 1.5

Posted via ActualForum NNTP Server 1.5

А ты внимательно читал текст по ссылке?

P.S. Проверять лень, но уверен, что ты просто
не разобрался, MSDN тоже подтверждает это.

Posted via ActualForum NNTP Server 1.5

Posted via ActualForum NNTP Server 1.5

> MS рекомендует всем вставить в свои программы код,
> который уберёт текущий каталог из путей поиска

Это совсем другое дело, хотя тоже не совсем полное отражение дел.
Не говоря уже о том, что рекомендации можно смело игнорировать.

Posted via ActualForum NNTP Server 1.5

F1 + LoadLibrary(Ex):

MSDN
The search path can be altered using the SetDllDirectory function. This solution is recommended instead of using SetCurrentDirectory or hard-coding the full path to the DLL. However, be aware that using SetDllDirectory effectively disables safe DLL search mode while the specified directory is in the search path and it is not thread safe. If possible, it is best to use AddDllDirectory to modify a default process search path. For more information, see Dynamic-Link Library Search Order.

(выделение моё)

F1 + SetDllDirectory:

MSDN
After calling SetDllDirectory, the standard DLL search path is:
- The directory from which the application loaded.
- The directory specified by the lpPathName parameter.
- The system directory. Use the GetSystemDirectory function to get the path of this directory. The name of this directory is System32.
- The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
- The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
- The directories that are listed in the PATH environment variable.

В списке нет текущего каталога.

В списке есть текущий каталог.

MSDN
Standard Search Order for Desktop Applications
.
If SafeDllSearchMode is enabled, the search order is as follows:
- The directory from which the application loaded.
- The system directory. Use the GetSystemDirectory function to get the path of this directory.
- The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
- The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
- The current directory.
- The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.

Текущий каталог есть, но помещён почти последним.

Собственно конкретно про это написано тут:
Dynamic-Link Library Security.

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

1. Пользователи Dropbox

Если на вашем компьютере с Windows установлен Dropbox и вы столкнулись с этой ошибкой, первое, что вам нужно сделать, это удалить и переустановить драйверы видеокарты. Откройте диспетчер устройств из меню «Пуск» и дважды щелкните «Адаптеры дисплея», чтобы развернуть его.

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

2. Пользователи Autodesk

Обратите внимание на пользователей программного обеспечения Autodesk, которые также с помощью карты ATI. Кажется, здесь конфликт. Скопируйте это имя файла.

Нажмите клавиши Windows + S, чтобы открыть поиск и найти это имя файла. Щелкните правой кнопкой мыши, чтобы открыть расположение файла и переименовать файл в atig6pxx.dll.bak. У меня нет карты ATI, поэтому я не могу поделиться скриншотами, но процесс довольно прост. Не забудьте обновить драйверы видеоадаптера до последней версии. Посетите сайт производителя, чтобы загрузить их.

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

6. SFC и DISM

Он проверит и восстановит целостность системных файлов. Вы еще не закончили. Есть еще одна команда.

Делайте это по одному. Эти процессы могут занять некоторое время, поэтому убедитесь, что ваш ноутбук подключен к источнику питания.

Если вы установили и используете любую из этих двух программ, обновите их до последней версии с их официального сайта. Это еще более верно, если вы также играете в Minecraft на своем компьютере с Windows.

8. Безопасный режим и чистая загрузка.

Возможно, возник конфликт приложения или программного обеспечения. Вы можете начать с удаления любого недавно установленного программного обеспечения. Посмотрим, поможет ли это. Если нет, вам придется перезагружать компьютер в безопасном режиме и выполнять чистую загрузку по одному, чтобы увидеть, устраняет ли он сбой LoadLibrary с ошибкой 87 на вашем компьютере с Windows 10.

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

Следующий: Хотите узнать больше об использовании оборудования и информацию в Windows 10? Щелкните ссылку ниже, чтобы узнать больше.

В Linux и Mac при использовании dlopen() для загрузки разделяемой библиотеки, которая связана с другой библиотекой, если связывание не удается из-за отсутствия символа, вы можете получить имя отсутствующего символа с помощью dlerror() . Он говорит что-то вроде

Короткий ответ - вы не можете, потому что Windows просто не предоставляет такой информации.

2 ответа

Я нашел способ, используя терминал MSYS2. Другие методы могут работать с программным обеспечением с графическим интерфейсом. Главное предостережение заключается в том, что это невозможно сделать на чистом C / C ++ и выпустить для конечных пользователей. Это только для разработчиков, но это лучше, чем ничего.

Установите Инструменты отладки для Windows, загрузив Windows SDK и снятие отметки со всего, кроме инструментов отладки. Я могу ошибаться, но похоже, что при установке этого программного обеспечения в ядро ​​Windows устанавливается ловушка, позволяющая LoadLibrary() записывать подробную информацию в stderr.

Откройте терминал MSYS2 Mingw64 от имени администратора и запустите

Это выводит на терминал следующее, чтобы подтвердить, что реестр был изменен.

Используйте -sls вместо +sls , если вам нужно отменить, поскольку я считаю, что изменение происходит для всех программ, называемых main.exe в Windows глобально, а не только для вашего файла.

Затем запуск main.exe должен распечатать отладочную информацию в stderr, но, поскольку я отлаживаю приложение -mwindows , у меня это не работает.

Но по какой-то причине запуск двоичного файла с gdb MSYS2 позволяет выводить эту отладочную информацию на stderr. Установите mingw-w64-x86_64-gdb с помощью MSYS2, запустите gdb ./main.exe и введите run или r . Найдите раздел, похожий на следующий.

Большой! Там написано Procedure "foo" could not be located in DLL , значит, у нас есть отсутствующий символ, как в POSIX / UNIX dlopen() .

Хотя ответ Реми Лебо технически верен, определение отсутствующего символа с помощью GetLastError () все еще возможно на платформе Windows. Возможно, что для библиотеки, которую вы пытаетесь загрузить, также требуется библиотека, которую она не может загрузить. Эти уровни зависимости могут продолжаться для неизвестного количества уровней, но единственный ответ, который может определить GetLastError (), - это то, что был пропущенный символ. Один из таких методов - использование Dependency Walker.

Читайте также: