.Net Core 3 Single exe et fichiers de paramétrage

.Net Core 3 Single exe et fichiers de paramétrage

Single Exe

Vous venez de réaliser votre première application avec .net Core 3 et vous êtes très content de pouvoir la déployer de manière autonome en embarquement tout ce qui est nécessaire pour la faire tourner. Seulement voilà, une fois compilée, vous trouvez qu’il y a beaucoup trop de fichiers en plus du .exe. De nombreuses dll sont présentes. Parfois même plusieurs centaines. 

Rassurez-vous, il existe une solution pour pallier votre problème. Tout réunir au sein d’un seul fichier.   

Commençons par le début et avec un projet très intéressant : Un hello world! 

L’ensemble du code illustrant cet article se trouve sur github : https://github.com/niou128/Demos 

La création se fait en quelques clics en choisissant simplement de créer un projet console .net Core 3.  

Comme je le signalais dans le préambule de cet article, le point intéressant de .net Core 3 est de pouvoir générer un exécutable autonome qui ne dépend pas des Framework installés sur le poste du futur utilisateur. Pour ce faire, il suffit de choisir l’option publier dans Visual studio et sélectionner Autonome dans les options de publications. Il faut également choisir le système cible (ici win-x86). 

Il ne vous reste plus qu’à cliquer sur publier.  

Il est également possible de passer par une invite de commande : 

dotnet publish -r win-x86 -c Release --self-contained 

Cela crée donc un exécutable autonome mais qui doit malgré tout s’accompagner d’une centaine de DLL.  

L’exécution de SingleExe.exe permet de s’apercevoir que l’on affiche bien Hello World.  

C’est bien, mais délicat à partager vu le nombre de fichiers. Pour remédier à ça, il faut ouvrir le fichier csproj.  

Ajouter les lignes <PublishSingleFile>true</PublishSingleFile> et <RuntimeIdentifier>win-x86</RuntimeIdentifier>

La première ligne signifie que l’on souhaite un exe seul, la deuxième est dans ce cas indispensable et indique le système cible.  On obtient donc :

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

  <PropertyGroup> 
    <OutputType>Exe</OutputType> 
    <TargetFramework>netcoreapp3.0</TargetFramework> 
    <PublishSingleFile>true</PublishSingleFile> 
    <RuntimeIdentifier>win-x86</RuntimeIdentifier> 
  </PropertyGroup> 

</Project> 

Après une nouvelle publication, le résultat est sans appel. Il ne reste plus qu’un fichier. (Deux avec le pdb) 

C’est beaucoup mieux. Néanmoins, l’exécutable est un peu volumineux. Il existe une solution permettant de remédier un peu à ça.  

Dans le fichier csproj, ajouter la ligne <PublishTrimmed>true</PublishTrimmed>

Une nouvelle publication plus tard et on obtient :

  

Un exécutable beaucoup plus petit. Cette option permet de ne pas inclure les DLL qui ne sont pas utilisées dans le projet. Cela réduit donc la taille de l’exécutable finale. 

Une autre option est également disponible :  <PublishReadyToRun>true</PublishReadyToRun> . 

Elle alourdit un peu le poids de l’exécutable, mais elle permet d’accélérer le temps de démarrage de l’application en consommant moins de ressource. Le binaire contient du code natif que produit en général le « Just-In-Time compiler » (JIT). Le permet au JIT d’avoir moins de travail au démarrage, ce qui accélère ce dernier.  

Fichiers de paramétrages 

Notre application est maintenant générée sous la forme d’un seul exe. Seulement voilà, nous souhaitons à présent choisir le texte affiché depuis un fichier de paramétrage.  

Ajoutez un fichier appsettings.json contenant le code suivant : 

{ 
   "Message": { 
    "Helloworld": "Hello World!" 
  } 
} 

Pensez à modifier les propriétés du fichier pour le mettre en copier si plus récent

Ajoutez ensuite les paquets NuGet : 

  • Microsoft.Extensions.Configuration 
  • Microsoft.Extensions.Configuration.FileExtensions 
  • Microsoft.Extensions.Configuration.Json 
  • Microsoft.Extensions.Configuration.Binder 

Nous allons maintenant ajouter une classe pour mapper notre configuration.  

Ajoutez la classe suivante :

public class Message 
{ 
    public string Helloworld { get; set; } 
} 

Dans le fichier programs.cs de notre exemple, modifiez la fonction main de la manière suivante :  

static void Main(string[] args) 

        { 

            var builder = new ConfigurationBuilder()            
 .SetBasePath(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)) 
          .AddJsonFile("appsettings.json"); 


            var config = builder.Build(); 

            var message = config.GetSection("Message").Get<Message>(); 

            Console.WriteLine(message.Helloworld); 

        } 

Republiez et à l’exécution on constate que l’on a toujours Hello Word! d’afficher.  

Remplacez dans le fichier appsettings la partie message par ceci : 

"Message": { 
    "Helloworld": "Coucou les amis" 
  } 

Republiez à nouveau et on constate que l’affichage à bien changé. 

Le problème que l’on note tout de suite c’est qu’à chaque modification du fichier de paramétrage, il faut republier l’application. 

On ne peut donc pas changer la configuration à la volée, car le fichier de paramétrage est inclus dans l’exe.  

Pour remédier à ce problème, il faut préciser que l’on veut sortir ce fichier et avoir à la fin un fichier exe et un fichier de paramétrage.  

Rendez-vous dans le fichier csproj et ajoutez la ligne <ExcludeFromSingleFile>true</ExcludeFromSingleFile> pour le fichier concerné.  

<ItemGroup> 

    <Content Include="appsettings.json"> 

      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 

      <ExcludeFromSingleFile>true</ExcludeFromSingleFile> 

    </Content> 

  </ItemGroup> 

Et on va légèrement modifier le fichier program.cs pour aller chercher le fichier de paramétrage à l’emplacement de l’exe. Il suffit de remplacer l’ancien SetBasepath par celui-ci :  

.SetBasePath(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)) 

Publiez une nouvelle. On constate qu’il y a maintenant le fichier exe et le fichier appsettings.json

Exécutez le fichier exe. Le résultat est toujours Coucou les amis

Ouvrez maintenant le fichier appsettings.json situé dans le répertoire de l’exe et modifiez la valeur de Helloworld :

{ 
  "Message": { 
    "Helloworld": "Appel externe" 
  } 
} 

Exécutez le fichier single.exe. 

Le message est maintenant Appel externe. 

Conclusion

Au sein de cet article, nous avons vu que quelques options suffisent pour générer un exécutable autonome tout en ayant la possibilité de sortir les fichiers de paramétrage.  

Laisser un commentaire