Можно ли запустить консольное приложение с использованием только одного файла в .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 в консольном приложении:

  1. Ссылка на пакет Microsoft.DotNet.ILCompiler в вашем выходном проекте. Вам нужно будет добавить репозиторий пакетов MyGet в настройках Visual Studio. *
  2. Опубликуйте проект через командную строку, dotnet опубликуйте C:\src\App\App.csproj -c release -r win-x64 -o output-win-x64. Если не установлен компонент "Разработка рабочего стола для C++", сделайте это в Visual Studio Installer, иначе команда не будет выполнена.
  3. Перейдите в папку вывода (например, "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