Можно ли запустить консольное приложение с использованием только одного файла в .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, которая еще находилась в стадии разработки, нацелена на то, чтобы позволить создать один предварительно скомпилированный собственный исполняемый файл, специфичный для среды выполнения и не требующий никаких других файлов.
Ответ 2
Протестировано с .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 Installer, иначе команда не будет выполнена.
- Перейдите в папку вывода (например, "C:\src\App\output-win-x64") и возьмите собственное изображение (файл .exe).
В Windows он создал полнофункциональный 5-мегабайтный файл .exe (по сравнению с оригинальной собственной -c публикацией с размером папки ~ 60 Мб). В macOS ILComplier, хотя и выводил данные без каких-либо ошибок, приложение зависало с необработанным ожиданием (на строке с выражением LINQ).
* Перейдите в "Инструменты → Параметры → Диспетчер пакетов → Источники пакетов" и добавьте новый источник по адресу https://dotnet.myget.org/F/dotnet-core/api/v3/index.json.
Ответ 3
Это возможно в .NET Core 3.0
Эта функция включена с помощью следующего свойства в файле проекта (.csproj):
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
Существуют и другие варианты, такие как упаковка pdb в пакет или отсутствие определенных файлов.
Найти документацию нелегко (так как это все еще предварительный просмотр), но есть обширный документ со стадии предложения, определяющий его использование: https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md
Правда это просто работает:
Сочетая эту технику с рабочим процессом Self-Contained Deployment, вы можете получить истинный опыт "это просто работает" для вашего пользователя, им даже не нужно устанавливать среду выполнения .NET Core для запуска вашего приложения.
В настоящее время я развертываю приложения на своих клиентах в виде отдельных файлов .exe.
Подробнее об этом читайте здесь: https://docs.microsoft.com/en-us/dotnet/core/deploying/#self-contained-deployments-scd