Развертывание с одним файлом

Объединение всех зависящих от приложения файлов в один двоичный файл предоставляет разработчику приложения привлекательный вариант развертывания и распространения приложения в виде одного файла. Развертывание с одним файлом доступно как для модели развертывания, зависящей от платформы , так и для автономных приложений.

Размер одного файла в автономном приложении велик, так как он включает среду выполнения и библиотеки платформы. В .NET 6 можно опубликовать обрезку , чтобы уменьшить общий размер приложений, совместимых с обрезкой. Вариант развертывания в виде одного файла можно сочетать с параметрами публикации ReadyToRun и Обрезка.

Внимание

Чтобы запустить одно файловое приложение в Windows 7, необходимо использовать среду выполнения .NET 6.0.3 или более позднюю версию.

Пример файла проекта

Ниже приведен пример файла проекта, который указывает публикацию отдельных файлов:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <PublishSingleFile>true</PublishSingleFile>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  </PropertyGroup>

</Project>

Эти свойства имеют следующие функции:

  • PublishSingleFile. Включает публикацию одного файла. Также включает предупреждения одного файла во время dotnet build.
  • SelfContained. Определяет, является ли приложение автономным или зависимым от платформы.
  • RuntimeIdentifier. Указывает целевой тип ОС и ЦП. Также задает по <SelfContained>true</SelfContained> умолчанию.

Одно файловые приложения всегда зависят от ОС и архитектуры. Для каждой конфигурации необходимо опубликовать такие конфигурации, как Linux x64, Linux Arm64, Windows x64 и т. д.

Файлы конфигурации среды выполнения, такие как *.runtimeconfig.json и *.deps.json, включаются в один файл.

Публикация однофайловых приложений

Опубликуйте приложение с одним файлом с помощью команды dotnet publish.

  1. Добавьте <PublishSingleFile>true</PublishSingleFile> в файл проекта.

    Это изменение создает одно файловое приложение для автономной публикации. В нем также отображаются предупреждения о совместимости отдельных файлов во время сборки.

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>
    
  2. Публикация приложения для определенного идентификатора среды выполнения с помощью dotnet publish -r <RID>

    В следующем примере приложение для Windows публикуется как автономное приложение с одним файлом.

    dotnet publish -r win-x64

    В следующем примере приложение для Linux публикуется как зависимое от платформы приложение с одним файлом.

    dotnet publish -r linux-x64 --self-contained false

<PublishSingleFile> Необходимо задать в файле проекта, чтобы включить анализ файлов во время сборки, но эти параметры также можно передать в качестве dotnet publish аргументов:

dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained false

Дополнительные сведения см. в статье Публикация приложений .NET с помощью интерфейса командной строки.

Исключить файлы из внедрения

Некоторые файлы можно явно исключить из внедренного в один файл, задав следующие метаданные:

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

Например, чтобы поместить некоторые файлы в каталог публикации, но не упаковать их в файл:

<ItemGroup>
  <Content Update="Plugin.dll">
    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
  </Content>
</ItemGroup>

Добавление PDB-файлов в пакет

PDB-файл для сборки можно внедрить в саму сборку (.dll), используя параметр, приведенный ниже. Так как символы являются частью сборки, они также являются частью приложения:

<DebugType>embedded</DebugType>

Например, добавьте следующее свойство в файл проекта сборки, чтобы внедрить PDB-файл в эту сборку:

<PropertyGroup>
  <DebugType>embedded</DebugType>
</PropertyGroup>

Другие вопросы

Одно файловые приложения имеют все связанные PDB-файлы вместе с приложением, а не пакет по умолчанию. Если вы хотите включить PDOB-файлы в сборку для проектов, которые вы создаете, задайте для DebugType него значение embedded. См. раздел "Включить PDB-файлы в пакет".

Управляемые компоненты C++ не подходят для развертывания одного файла. Рекомендуется создавать приложения на C# или другом неуправляемом языке C++ для совместимости с одним файлом.

Собственные библиотеки

Только управляемые библиотеки DLL объединяются с приложением в один исполняемый файл. При запуске приложения управляемые библиотеки DLL извлекаются и загружаются в память, что позволяет избежать извлечения в папку. При таком подходе управляемые двоичные файлы внедрены в один пакет файлов, но собственные двоичные файлы основной среды выполнения являются отдельными файлами.

Чтобы внедрить эти файлы для извлечения и получить один выходной файл, задайте для свойства IncludeNativeLibrariesForSelfExtract значение true.

Указание IncludeAllContentForSelfExtract извлечения всех файлов, включая управляемые сборки, перед запуском исполняемого файла. Это может быть полезно для редких проблем совместимости приложений.

Внимание

Если используется извлечение, файлы извлекаются на диск перед запуском приложения:

  • DOTNET_BUNDLE_EXTRACT_BASE_DIR Если переменная среды имеет путь, файлы извлекаются в каталог под этим путем.
  • В противном случае, если выполняется в Linux или macOS, файлы извлекаются в каталог в разделе $HOME/.net.
  • При запуске в Windows файлы извлекаются в каталог в разделе %TEMP%/.net.

Чтобы предотвратить изменение, эти каталоги не должны быть записаны пользователями или службами с разными привилегиями. Не используйте /tmp или /var/tmp в большинстве систем Linux и macOS.

Примечание.

В некоторых средах Linux, таких как в разделе systemd, извлечение по умолчанию не работает, так как $HOME не определено. В таких случаях рекомендуется явно задать $DOTNET_BUNDLE_EXTRACT_BASE_DIR .

В качестве systemdальтернативы можно определить DOTNET_BUNDLE_EXTRACT_BASE_DIR в файле единицы %h/.netслужбы, который systemd правильно расширяется для $HOME/.net учетной записи, в которой выполняется служба.

[Service]
Environment="DOTNET_BUNDLE_EXTRACT_BASE_DIR=%h/.net"

Несовместимость API

Некоторые API не совместимы с развертыванием одного файла. Приложения могут потребовать изменения, если они используют эти API. Если вы используете стороннюю платформу или пакет, возможно, они могут использовать один из этих API и нуждаться в изменении. Распространенная причина многих проблем — это зависимость от путей к файлам или библиотекам DLL, поставляемых с приложением.

В таблице ниже приведены сведения об API библиотеки среды выполнения для использования одного файла.

API Примечание.
Assembly.CodeBase Бросает PlatformNotSupportedException.
Assembly.EscapedCodeBase Бросает PlatformNotSupportedException.
Assembly.GetFile Бросает IOException.
Assembly.GetFiles Бросает IOException.
Assembly.Location Возвращает пустую строку.
AssemblyName.CodeBase Возвращает null.
AssemblyName.EscapedCodeBase Возвращает null.
Module.FullyQualifiedName Возвращает строку со значением <Unknown> или вызывает исключение.
Marshal.GetHINSTANCE Возвращает значение -1.
Module.Name Возвращает строку со значением <Unknown>.

Вот некоторые рекомендации по исправлению для распространенных сценариев:

  • Чтобы получить доступ к файлам, расположенным рядом с исполняемым файлом, используйте AppContext.BaseDirectory.

  • Чтобы найти имя файла исполняемого файла, используйте первый элемент Environment.GetCommandLineArgs()или начиная с .NET 6, используйте имя файла из ProcessPath.

  • Чтобы не допустить доставку свободных файлов в целом, используйте внедренные ресурсы.

Перед объединением двоичных файлов после обработки

Для некоторых рабочих процессов требуется после обработки двоичных файлов перед объединением. Типичным примером является подпись. Пакет SDK dotnet предоставляет точки расширения MSBuild, чтобы разрешить обработку двоичных файлов непосредственно перед объединением одного файла. Доступные API:

  • Целевой объект PrepareForBundle , который будет вызываться раньше GenerateSingleFileBundle
  • Содержащий <ItemGroup><FilesToBundle /></ItemGroup> все файлы, которые будут упаковыванием
  • Свойство AppHostFile , указывающее шаблон apphost. После обработки может потребоваться исключить apphost из обработки.

Чтобы подключиться к этому, необходимо создать целевой объект, который будет выполняться между PrepareForBundle и GenerateSingleFileBundle.

Рассмотрим следующий пример узла проекта Target .NET:

<Target Name="MySignedBundledFile" BeforeTargets="GenerateSingleFileBundle" DependsOnTargets="PrepareForBundle">

Возможно, что средства потребуется скопировать файлы в процессе подписания. Это может произойти, если исходный файл является общим элементом, не принадлежащим сборке, например, файл поступает из кэша NuGet. В таком случае ожидается, что средство изменит путь соответствующего FilesToBundle элемента, чтобы указать на измененную копию.

Сжатие сборок в однофайловых приложениях

Однофайловые приложения можно создавать с включенным сжатием в внедренных сборках. Установите свойство EnableCompressionInSingleFile в значение true. Один созданный файл будет иметь все внедренные сборки сжатыми, что может значительно уменьшить размер исполняемого файла.

Однако из-за этого может снизиться производительность. При запуске приложения сборки распаковываются в память, что занимает некоторое время. Рекомендуется измерять как изменение размера, так и стоимость запуска включения сжатия перед его использованием. Влияние может значительно отличаться между различными приложениями.

Проверка однофайловых приложений

Одно файловые приложения можно проверить с помощью средства ILSpy. Средство может отображать все файлы, упакованные в приложение, и может проверять содержимое управляемых сборок.

См. также