#c# #c #vb.net #pinvoke #dllnotfoundexception
#c# #c #vb.net #pinvoke #исключение DllNotFoundException
Вопрос:
У меня есть сторонняя DLL для интеграции с их приложением. Это 32-разрядная C DLL, которая не предоставляет себя через COM, и мне не был предоставлен исходный код или файл заголовка.
Он был снабжен рабочим VB.NET пример кода в примере WinForms. Это работает, если исполняемый файл запускается из того же каталога, что и DLL API, и приложение, с которым взаимодействует API.
Я использовал пример объявления функции:
Declare Ansi Function GetVersion Lib "ThirdPartyAPI.dll" () As Integer
Однако мы будем использовать вызовы API из библиотеки C # для использования на веб-сайте или веб-службе, поэтому я преобразовал пример кода VB в
[DllImport("ThirdPartyAPI.dll", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern int GetVersion();
Если я вызываю это из библиотеки C #, я получаю сообщение об ошибке
Unhandled Exception: System.DllNotFoundException: Unable to load DLL
'ThirdPartyAPI.dll': A dynamic link library (DLL) initialization
routine failed. (Exception from HRESULT: 0x8007045A)
Я выбрал альтернативный маршрут и вставил исходный рабочий код VB из примера в его собственный VB.NET DLL и вызвал это через C #. Я получил ту же ошибку. Как ни странно, вызов VB.NET DLL из VB.NET консольное приложение работает.
В итоге:
- Простой VB.NET консольное приложение будет работать
- Простой VB.NET Приложение WinForms будет работать
- Простой VB.NET консольное приложение может вызывать GetVersion через VB.NET DLL
- Простое консольное приложение C # не может вызвать GetVersion через VB.NET DLL
- Простое консольное приложение C # не может вызвать GetVersion напрямую. Это может быть связано с неправильным определением вызовов функций. На данном этапе я не слишком беспокоюсь об этом.
- 32-разрядная компиляция не устраняет проблему
- Я пробовал это на сервере 2008 R2 и Windows 7 Enterprise
Я создал хост WCF через службу NT для предоставления функций, надеясь, что это будет работать с расположением файлов и зависимостями. Это было написано в VB.NET и помещается в ту же папку, что и ThirdPartyApi.dll .
- Ни один код в службе NT не может получить доступ к GetVersion
- Ни один код в службе WCF не может получить доступ к GetVersion
Пожалуйста, обратите внимание, что во всех вышеуказанных случаях исполняемые файлы находятся в том же каталоге, что и ThirdPartyApi.dll . Все его зависимости также существуют в этом каталоге.
Кто-нибудь может объяснить это поведение или предложить, как это можно заставить работать на веб-сайте C #?
Спасибо
Комментарии:
1. Почему вы использовали
SetLastError = true
? И почему вы использовалиCharSet.Ansi
?2. Я не уверен
SetLastError = true
, но пример кода VB определил вызов какDeclare Ansi Function GetVersion Lib "ThirdPartyAPI.dll" () As Integer
, и этот код работает.3. Функция не имеет текстовых параметров, поэтому кодировка не имеет значения
Ответ №1:
Код ошибки 0x8007045A
. Это код ошибки COM, который сопоставляется с кодом ошибки Win32 ERROR_DLL_INIT_FAILED
. Который описывается как:
Сбой процедуры инициализации библиотеки динамических ссылок (DLL).
Это означает, что ваша DLL была найдена, несмотря на, возможно, вводящий в заблуждение класс исключения DllNotFoundException
. Однако DLL не удалось загрузить. Вы не можете получить больше информации от системы. Для DLL нет механизма, позволяющего сообщать о причинах, по которым не удалось загрузить. Я предлагаю вам связаться с поставщиком библиотеки DLL и обратиться за поддержкой.