Déploiement à fichier unique

Le regroupement de tous les fichiers dépendants de l’application dans un seul fichier binaire offre aux développeurs d’applications l’option intéressante de déployer et de distribuer l’application sous la forme d’un fichier unique. Le déploiement d’un fichier unique est disponible à la fois pour le modèle de déploiement dépendant de l’infrastructure et pour les applications autonomes.

La taille du fichier unique dans une application autonome est importante, car elle inclut le runtime et les bibliothèques d’infrastructure. Dans .NET 6, vous pouvez publier découpé pour réduire la taille totale des applications compatibles avec le découpage. L’option de déploiement de fichier unique peut être combinée avec les options de publication ReadyToRun et Trim.

Important

Pour exécuter une application à fichier unique sur Windows 7, vous devez utiliser le runtime .NET 6.0.3 ou version ultérieure.

Exemple de fichier projet

Voici un exemple de fichier projet qui spécifie la publication à fichier unique :

<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>

Ces propriétés ont les fonctions suivantes :

  • PublishSingleFile. Active la publication de fichiers uniques. Active également les avertissements de fichier unique pendant dotnet build.
  • SelfContained. Détermine si l’application est autonome ou dépendante de l’infrastructure.
  • RuntimeIdentifier. Spécifie le type de système d’exploitation et de processeur que vous ciblez. Définit également <SelfContained>true</SelfContained> par défaut.

Les applications à fichier unique sont toujours spécifiques au système d’exploitation et à l’architecture. Vous devez publier pour chaque configuration, par exemple Linux x64, Linux Arm64, Windows x64, etc.

Les fichiers de configuration du runtime, tels que *.runtimeconfig.json et *.deps.json, sont inclus dans le fichier unique. Si un fichier de configuration supplémentaire est nécessaire, vous pouvez le placer à côté du fichier unique.

Publier une application à fichier unique

Publiez une application à fichier unique à l’aide de la commande dotnet publish.

  1. Ajoutez <PublishSingleFile>true</PublishSingleFile> à votre fichier projet.

    Cette modification génère une application à fichier unique sur la publication autonome. Cela affiche également des avertissements de compatibilité à fichier unique pendant la génération.

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>
    
  2. Publiez l’application pour un identificateur d’exécution spécifique à l’aide de dotnet publish -r <RID>

    L’exemple suivant publie l’application pour Windows en tant qu’application à fichier unique autonome.

    dotnet publish -r win-x64

    L’exemple suivant publie l’application pour Linux en tant qu’application à fichier unique dépendante de l’infrastructure.

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

<PublishSingleFile> doit être défini dans le fichier projet pour activer l’analyse de fichier pendant la génération, mais il est également possible de passer ces options en tant qu’arguments dotnet publish :

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

Pour plus d’informations, consultez Publier des applications .NET Core avec CLI .NET.

Exclure des fichiers de l’incorporation

Certains fichiers peuvent être explicitement exclus de l’incorporation dans le fichier unique en définissant les métadonnées suivantes :

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

Par exemple, pour placer certains fichiers dans le répertoire de publication sans les regrouper dans le fichier :

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

Inclure des fichiers PDB dans le pack

Le fichier PDB d’un assembly peut être incorporé dans l’assembly lui-même (le .dll) à l’aide du paramètre ci-dessous. Étant donné que les symboles font partie de l’assembly, ils font également partie de l’application :

<DebugType>embedded</DebugType>

Par exemple, ajoutez la propriété suivante au fichier projet d’un assembly pour incorporer le fichier PDB à cet assembly :

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

Autres considérations

Les applications à fichier unique ont tous les fichiers PDB associés en même temps que l’application, et non groupés par défaut. Si vous souhaitez inclure des fichiers PDF à l’intérieur de l’assembly pour les projets que vous générez, définissez la valeur DebugType sur embedded. Consultez Inclure des fichiers PDB à l’intérieur de l’offre groupée.

Les composants C++ managés ne conviennent pas parfaitement au déploiement d’un fichier unique. Nous vous recommandons d’écrire des applications en C# ou dans un autre langage C++ non managé pour qu’elles soient compatibles avec un fichier unique.

Bibliothèques natives

Seules les bibliothèque de liens dynamiques (DLL) managées sont regroupées avec l’application dans un seul fichier exécutable. Lorsque l’application démarre, les DLL managées sont extraites et chargées en mémoire, ce qui évite l’extraction dans un dossier. Avec cette approche, les fichiers binaires managés sont incorporés dans le pack à fichier unique, mais les fichiers binaires natifs du runtime principal lui-même sont des fichiers distincts.

Pour incorporer ces fichiers pour l’extraction et obtenir un fichier de sortie, définissez la propriété IncludeNativeLibrariesForSelfExtract sur true.

La spécification de IncludeAllContentForSelfExtract extrait tous les fichiers, y compris les assemblys managés, avant d’exécuter l’exécutable. Cela peut être utile pour les rares problèmes de compatibilité d’application.

Important

Si l’extraction est utilisée, les fichiers sont extraits sur le disque avant le démarrage de l’application :

  • Si la variable d’environnement DOTNET_BUNDLE_EXTRACT_BASE_DIR est définie sur un chemin, les fichiers sont extraits dans un répertoire sous ce chemin.
  • Sinon, en cas d’exécution sur Linux ou macOS, les fichiers sont extraits dans un répertoire sous $HOME/.net.
  • En cas d’exécution sur Windows, les fichiers sont extraits dans un répertoire sous %TEMP%/.net.

Pour empêcher la falsification, ces répertoires ne doivent pas être accessibles en écriture par les utilisateurs ou les services disposant de privilèges différents. N’utilisez pas /tmp ou /var/tmp sur la plupart des systèmes Linux et macOS.

Notes

Dans certains environnements Linux, tels que sous systemd, l’extraction par défaut ne fonctionne pas, car $HOME n’est pas défini. Dans ce cas, nous vous recommandons de définir $DOTNET_BUNDLE_EXTRACT_BASE_DIR explicitement.

Pour systemd, une bonne alternative consiste à définir DOTNET_BUNDLE_EXTRACT_BASE_DIR dans le fichier d’unité de votre service en tant que %h/.net, que systemd étend correctement à $HOME/.net pour le compte exécutant le service.

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

Incompatibilité d’API

Certaines API ne sont pas compatibles avec le déploiement de fichiers uniques. Les applications peuvent nécessiter une modification si elles utilisent ces API. Si vous utilisez une infrastructure ou un package tiers, il est possible qu’ils utilisent l’une de ces API et nécessitent une modification. La cause la plus courante des problèmes est la dépendance vis-à-vis des chemins d’accès aux fichiers ou DLL fournis avec l’application.

Le tableau ci-dessous contient les détails pertinents de l’API de la bibliothèque de runtime pour l’utilisation d’un fichier unique.

API Notes
Assembly.CodeBase Lève PlatformNotSupportedException.
Assembly.EscapedCodeBase Lève PlatformNotSupportedException.
Assembly.GetFile Lève IOException.
Assembly.GetFiles Lève IOException.
Assembly.Location Retourne une chaîne vide.
AssemblyName.CodeBase Retourne null.
AssemblyName.EscapedCodeBase Retourne null.
Module.FullyQualifiedName Retourne une chaîne avec la valeur <Unknown> ou lève une exception.
Marshal.GetHINSTANCE Retourne -1.
Module.Name Retourne une chaîne avec la valeur <Unknown>.

Nous avons quelques recommandations pour résoudre les scénarios courants :

Fichiers binaires de post-traitement avant regroupement

Certains workflows nécessitent un post-traitement des fichiers binaires avant le regroupement. Un exemple courant est la signature. Le SDK dotnet fournit des points d’extension MSBuild pour permettre le traitement des fichiers binaires juste avant le regroupement à fichier unique. Les API disponibles sont les suivantes :

  • Un PrepareForBundle cible qui est appelé avant GenerateSingleFileBundle
  • Un <ItemGroup><FilesToBundle /></ItemGroup> contenant tous les fichiers qui sont regroupés
  • Une propriété AppHostFile qui spécifie le modèle d’apphost. Le post-traitement peut vouloir exclure l’apphost du traitement.

Pour mettre en place cette procédure, il est nécessaire de créer une cible destinée à être exécutée entre PrepareForBundle et GenerateSingleFileBundle.

Prenons l’exemple de nœud Target de projet .NET suivant :

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

Il est possible que les outils doivent copier des fichiers lors de la signature. Cela peut se produire si le fichier d’origine est un élément partagé qui n’appartient pas à la build, par exemple, si le fichier provient d’un cache NuGet. Dans ce cas, l’outil est censé modifier le chemin de l’élément FilesToBundle correspondant pour qu’il pointe vers la copie modifiée.

Compresser les assemblys dans des applications à fichier unique

Les applications à fichier unique peuvent être créées avec la compression activée sur les assemblys incorporés. Définissez la propriété EnableCompressionInSingleFile sur true. Le fichier unique produit aura tous les assemblys incorporés compressés, ce qui peut réduire considérablement la taille de l’exécutable.

La compression est accompagnée d’un coût de performance. Au démarrage de l’application, les assemblys doivent être décompressés en mémoire, ce qui prend un certain temps. Nous vous recommandons de mesurer à la fois le changement de taille et le coût de démarrage de l’activation de la compression avant de l’utiliser. L’impact peut varier considérablement entre différentes applications.

Inspecter une application à fichier unique

Les applications à fichier unique peuvent être inspectées à l’aide de l’outil ILSpy. L’outil peut afficher tous les fichiers regroupés dans l’application et inspecter le contenu des assemblys managés.

Voir aussi