Я пытаюсь вызвать DLL-метод из моего кода C++/CLI в Visual Studio .NET-DLL (v4.5) под названием «LicenseCheck.dll». Это работает нормально, пока эта DLL не попытается получить доступ к другой .NET-DLL с именем «SKCLNET.dll» (.NET v1.0.3705). Значение «LicenseCheck.dll» зависит от «SKCLNET.dll».
Когда я пытаюсь вызвать метод Licensecheck.dll "ValidateLicense::GetLicenseStatus()" из .NET-проекта, все работает нормально.
Вот ошибка, которую я получаю при запуске кода C++/CLI:
Необработанное исключение: System.BadImageFormatException: не удалось загрузить файл или сборку «SKCLNET.dll» или одна из его зависимостей. не является приложением Win32. (Исключение из HRESULT: 0x800700C1) в Seat.Core.LicenseProvider..ctor() в Seat.Core.LicenseProvider.get_Instance() в LicenseCheck.ValidateLicense.GetLicenseStatus() в main(String[] args) в C:\Users\deckenf\Desktop\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp:строка 13 в mainCRTStartupStrArray (аргументы String []) в D:\a_work\1\s\src\vctools\crt\crtw32\msilcrt\mcrtexe.cpp:строка 241 C:\Users\deckenf\Desktop\ConsoleApplication1\x64\Release\ConsoleApplication1.exe (процесс 33364) завершился с кодом -532462766.
Вот структура используемой dll:
Здесь класс ValidateLicense в .NET dll с функцией GetLicenseStatus(). Эта функция вызывается C++/CLI.
public static class ValidateLicense
{
public static string GetLicenseStatus()
{
return LicenseProvider.Instance.CheckLicense().ToString();
}
}
Вот еще некоторые детали сборки SKCLNET:
В первом абзаце вы несколько раз упоминаете LicenseCheck.dll. Разве вы не имели в виду SKCLNET.dll по крайней мере в некоторых из них? Также можете показать структуру SKCLNET.dll? (на вашем скриншоте показана только LicenseCheck.dll).
Кстати, о показе кода и т. д. в виде изображений см. здесь: meta.stackoverflow.com/questions/285551/….
System.BadImageFormatException
в 80 % случаев это связано с проблемами 32/64 бит. Убедитесь, что ваше приложение работает с теми же битами, что и библиотека.
В свойствах проекта > дополнительно > свойства C++/CLI. Установите поддержку Common Language Runtime, это может исправить это.
Хорошо получил его с изображением кода и удалил изображение. @wohlstand Я редактирую первый абзац, вы были правы. Когда я запускаю приложение с x86, оно выдает другую ошибку... Кажется, что LicenseCheck.sll — это x64, а SKCLNET.dll — это x86. Но, как я упоминал в вопросе, он работает, когда я запускаю его в проекте .NET с x64.
@wohlstand: см. скриншот обновленной структуры SKCLNET.dll.
Когда я запускаю приложение формы Windows, ошибка исчезает, когда я устанавливаю флажок в свойствах решения -> Сборка -> Общие -> Предпочитать 32-разрядную версию. Если этот параметр не отмечен, я получаю ту же ошибку, что и в проекте C++CLR. Кто-нибудь знает, как я могу установить этот параметр в проекте C++CLR? Варианты недвижимости совершенно разные.
Вы продолжаете называть SKCLNET.dll «встроенной» dll. Что это вообще значит? Если это управляемая сборка, для какой архитектуры она создана?
Название «встроенный» явно вводит в заблуждение, поэтому я отредактировал его в вопросе. Я предпочитаю собирать его для архитектуры x86, потому что он также может работать на архитектуре x64 из-за обратной совместимости, как я понял - поправьте меня, если я ошибаюсь.
Вы должны создать смешанный проект C++/CLI для Win32 или x64, так как неуправляемый код должен быть скомпилирован для соответствующей платформы. Откройте «Диспетчер конфигураций» в VS и проверьте правильную целевую платформу.
«ConsoleApplication1\x64\Release\ConsoleApplication1.exe» дает убедительный намек на то, что вы используете 64-разрядную сборку файла .exe. И ясно, что SKCLNET требует 32-битного процесса. Кабум. Если проект .exe является проектом C#, используйте вкладку «Проект» > «Свойства» > «Сборка», предпочитая 32-разрядную проверку. Повторите для конфигурации Release.
@ Ханс Пассант, ты был прав. Утром я провел небольшое исследование о том, как правильно настроить цели платформы для моего проекта C++/CLI. После сборки проекта C++/CLI для 32-разрядной версии появляется следующая ошибка (я также установил в App.config «useLegacyV2RuntimeActivationPolicy» = true, потому что это помогло запустить его в проекте C#): Unhandled Exception: System.IO. FileLoadException: сборка в смешанном режиме создана для версии среды выполнения v1.0.3705 и не может быть загружена в среде выполнения 4.0 без дополнительной информации о конфигурации.
Почему я получаю эту ошибку в своем проекте C++/CLI, но не в проекте C#?
После двух дней исследований я, наконец, нашел проблему. Как писал @Hans Passant в комментариях, ошибка в вопросе вызвана тем, что я создал .exe для 64-разрядной версии, хотя для SKCLNET.dll требуется 32-разрядный процесс.
Поскольку SKCLNET.dll нацелен на .NET v1.0.3705, также необходимо было добавить файл app.config в проект C++/CLI и добавить тег useLegacyV2RuntimeActivationPolicy
. Это параметр конфигурации в .NET Framework, который используется для управления политикой активации среды выполнения для приложений, использующих сборки смешанного режима. В .NET Framework 4 и более поздних версиях политика активации среды выполнения была изменена на новое поведение по умолчанию. Такое поведение по умолчанию может привести к сбою некоторых старых приложений, предназначенных для работы с более ранними версиями .NET Framework.
Последним важным шагом было копирование этого файла app.config после сборки по целевому пути. Для этого щелкните правой кнопкой мыши проект C++/CLI > Properties > Build -Events > Post-Build Event и для параметра Command Line
вставьте следующую строку:
copy app.config "$(TargetPath).config"
Эта статья помогла решить мою проблему.