У меня есть небольшое приложение .Net 7.0, которое нужно запускать как в Windows, так и в Linux. Приложению необходимо вызвать 32-битную dll с помощью pinvoke, поэтому выбор переносимого варианта невозможен. операционная система приложения настроена на платформы ARM32 и x86:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>ARM32;x86</Platforms>
</PropertyGroup>
все части приложения имеют эту конфигурацию. когда я запускаю приложение через VS 2022 или Rider, оно работает, как и ожидалось, на моем компьютере с Windows. Если я попытаюсь запустить сборку из bin или сборку выпуска приложения с помощью команды «dotnet», это не удастся.
Конфигурация выпуска:
Исключение:
Необработанное исключение. System.IO.FileLoadException: не удалось загрузить файл или сборка «EIS.Host, версия = 1.0.0.0, культура = нейтральная, ПубличныйКейТокен = ноль».
EIS.Host — имя Startup-проекта, запускающего приложение. Создаваемый exe-файл также называется «EIS.Host.exe».
Я пробовал разные конфигурации, например, добавив это в csproj:
<PropertyGroup Condition = " '$(Configuration)' == 'Debug' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition = " '$(Configuration)' == 'Release' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
после этого я переключился на текущую конфигурацию.
Я пробовал сборки с Rider и vs2022. я попробовал запустить вывод сборки и вывод вывода как для Arm32, так и для x86 через dotnet (x86 прямо на моей машине, Arm32 с использованием wsl2)
Введите «where dotnet.exe» в командной строке. Скорее всего, вы увидите его в c:\program files\dotnet, где находится 64-битная версия .net. Вместо этого используйте «c:\program files (x86)\dotnet\dotnet.exe».
Мне не удалось найти свойство MSBuild под названием Platforms
(например, его здесь нет). Вы уверены, что такое свойство существует? Я смог найти только Platform
. Возможно, IDE способны анализировать такое свойство, но команда dotnet
не может.
Я бы сначала попробовал это. В этом случае вы можете создать два файла проекта: один для Linux, а другой для архитектуры Windows. После этой настройки вы можете попытаться поместить его в один файл проекта.
Если это все еще не работает, попробуйте удалить вызов pinvoke, а затем удалите всю ненужную конфигурацию в файле проекта, который вы добавили только из-за pinvoke. Просто чтобы привести его в состояние, в котором вы сможете построить проект, используя dotnet build
. После этого попробуйте добавить только код pinvoke и конфигурацию проекта, например. для архитектуры Windows и снова попробуйте построить с помощью dotnet
. Делайте это итеративно, чтобы лучше определить, где именно возникла проблема. (У вас также могут возникнуть проблемы с самим dotnet cli
!).
Вы также можете попробовать удалить все файлы bin и obj вручную. Иногда dotnet clean
не удаляет все .dll
, что приводит к непредвиденным ошибкам во время build
.
разделение его на два файла проекта решило проблему, спасибо
Сомнительно, что p/invoke будет работать в Linux для библиотек Windows, хотя вам может повезти, если в системе работает WINE. Также сомнительно, что библиотека Windows, скомпилированная для x86/64, вообще будет работать на ARM, независимо от того, WINE или нет.