Есть ли способ заставить консольное приложение работать, используя только один файл в.NET Core?
В.NET Framework вы можете сделать один .EXE
файл, который будет запускаться из командной строки без каких-либо дополнительных файлов конфигурации (и если вы используете ILMerge, вы можете поместить все .DLL
ссылки в 1 .EXE
монтаж).
Я пытаюсь использовать.NET Core для достижения того же результата, но пока безуспешно. Даже самый простой Hello World
приложение без зависимостей требует наличия файла с именем <MyApp>.runtimeconfig.json
для того, чтобы запустить с помощью dotnet.exe
,
dotnet F:\temp\MyApp.dll
Содержание <MyApp>.runtimeconfig.json
являются следующими:
{
"runtimeOptions": {
"framework": {
"name": "Microsoft.NETCore.App",
"version": "1.1.1"
}
}
}
Без этого файла конфигурации в той же папке, что и .DLL
Я получаю следующую ошибку:
A fatal error was encountered. The library 'hostpolicy.dll' required to
execute the application was not found in 'F:\temp'.
Мой вопрос: есть ли какой-нибудь способ изменить приложение, чтобы он не требовал присутствия этого файла конфигурации, чтобы значения по умолчанию этой информации компилировались в .DLL
но можно переопределить, добавив файл конфигурации?
ПРИМЕЧАНИЕ. Я также хочу убедиться, что он "просто работает" независимо от платформы, на которой он установлен, при условии, что на платформе установлена правильная версия.NET Core.
Фон
Я пытаюсь получить удобный пользовательский опыт для запуска некоторых утилит, которые иногда полезны, но редко когда-либо необходимы. Поскольку представляется невозможным использовать тот же .DLL
на который ссылается клиентское приложение как на консольное приложение, лучше всего было бы иметь один файл, который можно было бы загрузить и запустить без каких-либо зависимостей.
Например, в Java вы можете просто скачать .jar
файл на любой поддерживаемой платформе и запустите:
java <package>.jar <namespace>.SomeClass [args]
и он будет "просто работать" без каких-либо дополнительных файлов. Как я могу получить аналогичный пользовательский опыт при использовании.NET Core?
Короче говоря, я хочу попытаться избежать дополнительного шага "сначала распаковать в каталог"...
1 ответ
Обновление 2018:.NET Core 3.0 призван обеспечить новый сценарий: упаковка среды выполнения.NET Core и всех зависимостей приложений в один исполняемый файл.
На данный момент не существует отказоустойчивых методов для создания одного исполняемого файла. Поскольку задействовано много dll-файлов для переадресации типов, даже ILMerge и аналогичные инструменты могут не давать правильных результатов (хотя это может улучшиться, проблема в том, что эти сценарии не прошли обширное тестирование, особенно в производственных приложениях)
В настоящее время существует два способа развертывания приложения.NET Core:
- Как "переносимое приложение" / "зависящее от фреймворка приложение", требующее
dotnet
исполняемый и установленный фреймворк на целевой машине. ЗдесьXYZ.runtimeconfig.json
используется для определения используемой версии платформы, а также для определения параметров времени выполнения. Эта модель развертывания позволяет запускать один и тот же код на разных платформах (windows, linux, mac) - Как "автономное приложение": здесь вся среда выполнения включена в опубликованный вывод и генерируется исполняемый файл (например,
yourapp.exe
). Эти выходные данные относятся к платформе (задается с помощью идентификатора среды выполнения) и могут выполняться только в целевой операционной системе. Тем не менее, производимый исполняемый файл является лишь небольшой оболочкой, которая загружает среду выполнения и загружает основной файл DLL приложения. Это также позволяетXYZ.runtimeconfig.json
установить дополнительные свойства времени выполнения, такие как настройки сборки мусора. (Думайте об этом как о "новом"app.config
файл)
В будущем среда выполнения CoreRT, которая еще находилась в стадии разработки, нацелена на то, чтобы позволить создать один предварительно скомпилированный собственный исполняемый файл, специфичный для среды выполнения и не требующий никаких других файлов.
Протестировано с.NET Core 2.2 в консольном приложении:
- Ссылка на пакет Microsoft.DotNet.ILCompiler в вашем выходном проекте. Вам нужно будет добавить репозиторий пакетов MyGet в настройках Visual Studio. *
- Опубликуйте проект через командную строку, dotnet опубликуйте C: \ src \ App \ App.csproj -c release -r win-x64 -o output-win-x64. Если не установлен компонент "Разработка рабочего стола для C++", выполните это в установщике Visual Studio, иначе команда не будет выполнена.
- Перейдите в папку вывода (например, "C:\src\App\output-win-x64") и возьмите собственное изображение (файл.exe).
В Windows он создал полнофункциональный файл размером 5 МБ.exe (по сравнению с оригинальной автономной публикацией с размером папки ~60 МБ). В macOS ILComplier, хотя и выводил данные без каких-либо ошибок, приложение зависало с необработанным ожиданием (на строке с выражением LINQ).
* Перейдите в "Инструменты -> Параметры -> Диспетчер пакетов -> Источники пакетов" и добавьте новый источник по адресу https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
Это возможно в.NET Core 3.0
Эта функция активируется при использовании следующего свойства в файле проекта (.csproj):
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
Есть и другие варианты, например, упаковка pdb в пакет или исключение определенных файлов.
Документацию найти нелегко (так как это все еще предварительная версия), но есть обширный документ со стадии предложения, в котором указывается его использование: https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md
Правда просто работает:
Комбинируя этот метод с рабочим процессом автономного развертывания, вы можете получить для своего пользователя истинный опыт "это просто работает", им даже не нужно устанавливать среду выполнения.NET Core для запуска вашего приложения.
В настоящее время я развертываю приложения для своих клиентов в виде отдельных файлов .exe.
Подробнее об этом читайте здесь: https://docs.microsoft.com/en-us/dotnet/core/deploying/