Исключение DllNotFoundException из C #, но не VB.NET

#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 и обратиться за поддержкой.