Incorporation de DLL dans un exécutable compilé

619

Est-il possible d'incorporer une DLL préexistante dans un exécutable C # compilé (afin que vous n'ayez qu'un seul fichier à distribuer)? Si c'est possible, comment procéder?

Normalement, je suis cool de simplement laisser les DLL à l'extérieur et d'avoir le programme d'installation gérer tout, mais il y a quelques personnes au travail qui m'ont demandé cela et je ne sais vraiment pas.

Merus
la source
Je vous recommande de vérifier l'utilitaire .NETZ, qui comprime également l'assembly avec un schéma de votre choix: http://madebits.com/netz/help.php#single
Nathan Baulch
2
C'est possible, mais vous vous retrouverez avec un grand exécutable (Base64 sera utilisé pour encoder votre DLL).
Paweł Dyda
Outre ILMerge , si vous ne voulez pas vous embêter avec les commutateurs de ligne de commande, je recommande vraiment ILMerge-Gui . C'est un projet open source, vraiment bon!
tyron
2
@ PawełDyda: Vous pouvez intégrer des données binaires brutes dans une image PE (voir RCDATA ). Aucune transformation requise (ou recommandée).
IInspectable

Réponses:

761

Je recommande fortement d'utiliser Costura.Fody - de loin la manière la meilleure et la plus simple d'incorporer des ressources dans votre assemblage. Il est disponible sous forme de package NuGet.

Install-Package Costura.Fody

Après l'avoir ajouté au projet, il incorporera automatiquement toutes les références copiées dans le répertoire de sortie dans votre assembly principal . Vous voudrez peut-être nettoyer les fichiers incorporés en ajoutant une cible à votre projet:

Install-CleanReferencesTarget

Vous pourrez également spécifier s'il faut inclure les pdb, exclure certains assemblages ou extraire les assemblages à la volée. Pour autant que je sache, les assemblys non gérés sont également pris en charge.

Mise à jour

Actuellement, certaines personnes essaient d'ajouter la prise en charge de DNX .

Update 2

Pour la dernière version de Fody, vous aurez besoin d'avoir MSBuild 16 (donc Visual Studio 2019). Fody version 4.2.1 fera MSBuild 15. (référence: Fody n'est pris en charge que sur MSBuild 16 et supérieur. Version actuelle: 15 )

Matthias
la source
79
Merci pour cette super suggestion. Installez le package et vous avez terminé. Il compresse même les assemblages par défaut.
Daniel
9
Je déteste être un «moi aussi», mais moi aussi - cela m'a évité beaucoup de maux de tête! Merci pour la recommandation! Cela m'a permis de regrouper tout ce dont j'ai besoin pour redistribuer dans un seul exe et il est maintenant plus petit que l'exe original et les DLL ont été combinés ... Je n'utilise cela que depuis quelques jours, donc je ne peux pas dire que je '' Je l'ai mis à l'épreuve, mais à moins que quelque chose de mauvais surgisse, je peux voir cela devenir un outil normal dans ma boîte à outils. Ça marche!
mattezell
20
C'est cool. Mais il y a un inconvénient: l'assembly généré sous Windows n'est plus compatible binaire avec mono Linux. Cela signifie que vous ne pouvez pas déployer l'assembly directement sur Linux mono.
Tyler Long
7
C'est adorable! Si vous utilisez vs2018, n'oubliez pas que le fichier FodyWeavers.xml se trouve à la racine de votre projet.
Alan Deep
4
En complément du dernier commentaire: ajoutez le FodyWeavers.xml avec le contenu suivant à votre projet: <? Xml version = "1.0" encoding = "utf-8"?> <Weavers VerifyAssembly = "true"> <Costura /> </Weavers>
HHenn
89

Faites simplement un clic droit sur votre projet dans Visual Studio, choisissez Propriétés du projet -> Ressources -> Ajouter une ressource -> Ajouter un fichier existant… Et incluez le code ci-dessous dans votre App.xaml.cs ou équivalent.

public App()
{
    AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");

    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);
}

Voici mon article de blog original: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/

Lars Holm Jensen
la source
6
Vous pouvez avoir ce comportement hors de la boîte. Découvrez ma réponse stackoverflow.com/a/20306095/568266
Matthias
4
Il est également important de noter un commentaire INCROYABLEMENT utile sur votre blog d'AshRowe: si vous avez installé un thème personnalisé, il essaiera de résoudre l'assembly PresentationFramework.Theme qui se bloque et brûle! Selon la suggestion d'AshRowe, vous pouvez simplement vérifier si le dllName contient PresentationFramework comme ceci: if (dllName.ToLower (). Contains ("presentationframework")) return null;
YasharBahman
4
Deux commentaires à ce sujet. Un: vous devez vérifier si bytesest nul, et si c'est le cas, renvoyez-y null. Il est possible que la DLL ne soit pas dans les ressources, après tout. Deux: cela ne fonctionne que si cette classe elle-même n'a pas de "utilisation" pour quoi que ce soit de cet assembly. Pour les outils de ligne de commande, j'ai dû déplacer mon code de programme réel vers un nouveau fichier et créer un petit nouveau programme principal qui fait juste cela, puis appelle le principal d'origine dans l'ancienne classe.
Nyerguds
2
L'avantage de cette approche est qu'elle ne repose pas sur l'installation de bibliothèques externes pour obtenir les fonctionnalités souhaitées. L'inconvénient de cette approche est qu'elle n'est utile qu'en ce qui concerne les DLL gérées - les DLL d'interopérabilité (du moins en ce qui concerne mes tests) ne déclenchent pas l'événement assemblyresolve et même si elles l'ont fait Assembly.Load (<octets d'une certaine interop .dll>) n'obtient pas l'effet souhaité sur la route. stackoverflow.com/questions/13113131/… Juste mon 2c sur la question
XDS
3
Juste au cas où quelqu'un rencontrerait mon problème: si le .dllnom contient des tirets (ie twenty-two.dll), ceux-ci seront également remplacés par un trait de soulignement (ie twenty_two.dll). Vous pouvez changer cette ligne de code en ceci:dllName = dllName.Replace(".", "_").Replace("-", "_");
Micah Vertal
87

S'ils sont réellement des assemblys gérés, vous pouvez utiliser ILMerge . Pour les DLL natives, vous aurez un peu plus de travail à faire.

Voir aussi: Comment une DLL Windows C ++ peut-elle être fusionnée dans un exe d'application C #?

Shog9
la source
Je suis intéressé par la fusion native de DLL, y a-t-il des matériaux?
Baiyan Huang
5
Voir aussi: stackoverflow.com/questions/108971/…
Milan Gardian
@BaiyanHuang regardez github.com/boxedapp/bxilmerge , l'idée est de faire "ILMerge" pour les DLL natives.
Artem Razin
Les développeurs VB NET comme moi n'ont pas peur de cela C++sur le lien. ILMerge fonctionne également très facilement pour VB NET. Voir ici https://github.com/dotnet/ILMerge . Merci @ Shog9
Ivan Ferrer Villa
26

Oui, il est possible de fusionner des exécutables .NET avec des bibliothèques. Il existe plusieurs outils disponibles pour effectuer le travail:

  • ILMerge est un utilitaire qui peut être utilisé pour fusionner plusieurs assemblys .NET en un seul assembly.
  • Mono mkbundle , empaquette un exe et tous les assemblages avec libmono dans un seul paquet binaire.
  • IL-Repack est une alternative FLOSS à ILMerge, avec quelques fonctionnalités supplémentaires.

De plus, cela peut être combiné avec le Mono Linker , qui supprime le code inutilisé et réduit donc l'assemblage résultant.

Une autre possibilité consiste à utiliser .NETZ , qui permet non seulement de compresser un assemblage, mais peut également compresser les DLL directement dans l'exe. La différence avec les solutions mentionnées ci-dessus est que .NETZ ne les fusionne pas, ils restent des assemblages séparés mais sont regroupés dans un seul package.

.NETZ est un outil open source qui compresse et compresse les fichiers exécutables (EXE, DLL) Microsoft .NET Framework afin de les réduire.

Policier
la source
NETZ semble avoir disparu
Rbjz
Wow - je pensais l'avoir enfin trouvé, alors j'ai lu ce commentaire. Il semble avoir totalement disparu. Y a-t-il des fourchettes?
Mafii
Eh bien, il vient de migrer vers GitHub et il n'est plus lié sur le site Web ... donc "disparu totalement" est une surestimation. Très probablement, il n'est plus pris en charge, mais il est toujours là. J'ai mis à jour le lien.
Bobby
20

ILMerge peut combiner des assemblys en un seul assembly à condition que l'assembly ne dispose que de code managé. Vous pouvez utiliser l'application de ligne de commande ou ajouter une référence à l'exe et fusionner par programme. Pour une version GUI, il y a Eazfuscator , et aussi .Netz, tous deux gratuits. Les applications payantes incluent BoxedApp et SmartAssembly .

Si vous devez fusionner des assemblys avec du code non managé , je suggère SmartAssembly . Je n'ai jamais eu de hoquet avec SmartAssembly mais avec tous les autres. Ici, il peut intégrer les dépendances requises en tant que ressources à votre exe principal.

Vous pouvez faire tout cela manuellement sans avoir à vous inquiéter si l'assembly est géré ou en mode mixte en intégrant la DLL à vos ressources, puis en s'appuyant sur l'assembly d'AppDomain ResolveHandler. Il s'agit d'une solution à guichet unique en adoptant le pire des cas, à savoir les assemblys avec du code non managé.

static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string assemblyName = new AssemblyName(args.Name).Name;
        if (assemblyName.EndsWith(".resources"))
            return null;

        string dllName = assemblyName + ".dll";
        string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);

        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
        {
            byte[] data = new byte[stream.Length];
            s.Read(data, 0, data.Length);

            //or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);

            File.WriteAllBytes(dllFullPath, data);
        }

        return Assembly.LoadFrom(dllFullPath);
    };
}

La clé ici est d'écrire les octets dans un fichier et de les charger à partir de son emplacement. Pour éviter les problèmes de poule et d'oeuf, vous devez vous assurer de déclarer le gestionnaire avant d'accéder à l'assemblage et de ne pas accéder aux membres de l'assemblage (ou instancier tout ce qui doit traiter l'assemblage) à l'intérieur de la pièce de chargement (résolution d'assemblage). Veillez également à ce qu'il GetMyApplicationSpecificPath()n'y ait pas de répertoire temporaire car les fichiers temporaires pourraient être effacés par d'autres programmes ou par vous-même (non pas qu'il sera supprimé pendant que votre programme accède à la DLL, mais au moins c'est une nuisance. AppData est bon emplacement). Notez également que vous devez écrire les octets à chaque fois, vous ne pouvez pas charger à partir de l'emplacement, car la DLL y réside déjà.

Pour les DLL gérées, vous n'avez pas besoin d'écrire d'octets, mais de charger directement à partir de l'emplacement de la DLL, ou simplement de lire les octets et de charger l'assembly à partir de la mémoire. Comme ceci ou cela:

    using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
    {
        byte[] data = new byte[stream.Length];
        s.Read(data, 0, data.Length);
        return Assembly.Load(data);
    }

    //or just

    return Assembly.LoadFrom(dllFullPath); //if location is known.

Si l'assembly n'est pas entièrement géré, vous pouvez voir ce lien ou ceci pour savoir comment charger de telles DLL.

nawfal
la source
Notez que «Build Action» de la ressource doit être définie sur «Embedded Resource».
Mavamaarten
@Mavamaarten Pas nécessairement. S'il est ajouté à l'avance au Resources.resx du projet, vous n'avez pas besoin de le faire.
Nyerguds
2
EAZfuscator est maintenant commercial.
Telemat
16

L' extrait de Jeffrey Richter est très bon. En bref, ajoutez les bibliothèques en tant que ressources intégrées et ajoutez un rappel avant toute autre chose. Voici une version du code (trouvée dans les commentaires de sa page) que j'ai mise au début de la méthode Main pour une application console (assurez-vous simplement que tous les appels qui utilisent les bibliothèques sont dans une méthode différente de Main).

AppDomain.CurrentDomain.AssemblyResolve += (sender, bargs) =>
        {
            String dllName = new AssemblyName(bargs.Name).Name + ".dll";
            var assem = Assembly.GetExecutingAssembly();
            String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName));
            if (resourceName == null) return null; // Not found, maybe another handler will find it
            using (var stream = assem.GetManifestResourceStream(resourceName))
            {
                Byte[] assemblyData = new Byte[stream.Length];
                stream.Read(assemblyData, 0, assemblyData.Length);
                return Assembly.Load(assemblyData);
            }
        };
Steve
la source
1
J'ai un peu changé, fait le boulot, mon pote tnx!
Sean Ed-Man,
Le projet libz.codeplex.com utilise ce processus, mais il fera aussi d'autres choses comme gérer le gestionnaire d'événements pour vous et du code spécial pour ne pas casser les " catalogues du cadre d'extensibilité gérée " (qui par lui-même ce processus se briserait)
Scott Chamberlain
C'est génial!! Merci @Steve
Ahmer Afzal
14

Pour développer la réponse de @ Bobby ci- dessus. Vous pouvez modifier votre .csproj pour utiliser IL-Repack pour empaqueter automatiquement tous les fichiers dans un seul assembly lors de la génération.

  1. Installez le package nuget ILRepack.MSBuild.Task avec Install-Package ILRepack.MSBuild.Task
  2. Modifiez la section AfterBuild de votre .csproj

Voici un exemple simple qui fusionne ExampleAssemblyToMerge.dll dans la sortie de votre projet.

<!-- ILRepack -->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

   <ItemGroup>
    <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
    <InputAssemblies Include="$(OutputPath)\ExampleAssemblyToMerge.dll" />
   </ItemGroup>

   <ILRepack 
    Parallel="true"
    Internalize="true"
    InputAssemblies="@(InputAssemblies)"
    TargetKind="Exe"
    OutputFile="$(OutputPath)\$(AssemblyName).exe"
   />
</Target>
Josh
la source
1
La syntaxe pour IL-Repack a changé, vérifiez le fichier README.md qui se trouve sur le référentiel github lié ( github.com/peters/ILRepack.MSBuild.Task ). Cette façon était la seule qui fonctionnait pour moi et j'ai pu utiliser un caractère générique pour correspondre à toutes les DLL que je voulais inclure.
Seabass77
8

Vous pouvez ajouter les DLL en tant que ressources intégrées, puis demander à votre programme de les décompresser dans le répertoire de l'application au démarrage (après avoir vérifié si elles s'y trouvent déjà).

Cependant, les fichiers d'installation sont si faciles à créer que je ne pense pas que cela en vaille la peine.

EDIT: Cette technique serait facile avec les assemblys .NET. Avec des DLL non .NET, ce serait beaucoup plus de travail (il faudrait trouver où décompresser les fichiers et les enregistrer, etc.).

MusiGenesis
la source
Ici vous avez un article qui explique comment faire: codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource
bleu
8

Un autre produit qui peut gérer cela avec élégance est SmartAssembly, sur SmartAssembly.com . Ce produit, en plus de fusionner toutes les dépendances dans une seule DLL, (facultativement) obscurcira votre code, supprimera les métadonnées supplémentaires pour réduire la taille du fichier résultant, et peut également réellement optimiser l'IL pour augmenter les performances d'exécution.

Il existe également une sorte de fonctionnalité de gestion / rapport d'exception globale qu'il ajoute à votre logiciel (si vous le souhaitez) qui pourrait être utile. Je crois qu'il dispose également d'une API de ligne de commande afin que vous puissiez l'intégrer à votre processus de génération.

Nathan
la source
7

Ni l'approche ILMerge ni la gestion par Lars Holm Jensen de l'événement AssemblyResolve ne fonctionneront pour un hôte de plugin. Supposons que l'exécutable H charge l'assembly P de manière dynamique et y accède via l'interface IP définie dans un assembly séparé. Pour intégrer IP dans H , il faudra une petite modification du code de Lars:

Dictionary<string, Assembly> loaded = new Dictionary<string,Assembly>();
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{   Assembly resAssembly;
    string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
    dllName = dllName.Replace(".", "_");
    if ( !loaded.ContainsKey( dllName ) )
    {   if (dllName.EndsWith("_resources")) return null;
        System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
        byte[] bytes = (byte[])rm.GetObject(dllName);
        resAssembly = System.Reflection.Assembly.Load(bytes);
        loaded.Add(dllName, resAssembly);
    }
    else
    {   resAssembly = loaded[dllName];  }
    return resAssembly;
};  

L'astuce pour gérer les tentatives répétées pour résoudre le même assembly et renvoyer l'existant au lieu de créer une nouvelle instance.

EDIT: de peur de gâcher la sérialisation de .NET, assurez-vous de retourner null pour tous les assemblys non intégrés dans le vôtre, ce qui revient par défaut au comportement standard. Vous pouvez obtenir une liste de ces bibliothèques en:

static HashSet<string> IncludedAssemblies = new HashSet<string>();
string[] resources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
for(int i = 0; i < resources.Length; i++)
{   IncludedAssemblies.Add(resources[i]);  }

et renvoyez simplement null si l'assembly passé n'appartient pas IncludedAssemblies.

Ant_222
la source
Désolé de l'avoir publié comme réponse plutôt que comme commentaire. Je n'ai pas le droit de commenter les réponses des autres.
Ant_222
5

.NET Core 3.0 prend en charge nativement la compilation en un seul .exe

La fonctionnalité est activée par l'utilisation de la propriété suivante dans votre fichier de projet (.csproj):

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>

Cela se fait sans aucun outil externe.

Voir ma réponse à cette question pour plus de détails.

Marcell Toth
la source
3

Cela peut sembler simpliste, mais WinRar donne la possibilité de compresser un tas de fichiers en un exécutable auto-extractible.
Il a beaucoup d'options configurables: icône finale, extraire les fichiers vers un chemin donné, fichier à exécuter après l'extraction, logo / textes personnalisés pour la fenêtre contextuelle affichée pendant l'extraction, pas de fenêtre contextuelle du tout, texte du contrat de licence, etc.
Peut être utile dans certains cas .

Villa Ivan Ferrer
la source
Windows lui-même dispose d'un outil similaire appelé iexpress. Voici un tutoriel
Ivan Ferrer Villa
2

J'utilise le compilateur csc.exe appelé à partir d'un script .vbs.

Dans votre script xyz.cs, ajoutez les lignes suivantes après les directives (mon exemple est pour le Renci SSH):

using System;
using Renci;//FOR THE SSH
using System.Net;//FOR THE ADDRESS TRANSLATION
using System.Reflection;//FOR THE Assembly

//+ref>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+res>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+ico>"C:\Program Files (x86)\Microsoft CAPICOM 2.1.0.2 SDK\Samples\c_sharp\xmldsig\resources\Traffic.ico"

Les balises ref, res et ico seront récupérées par le script .vbs ci-dessous pour former la commande csc.

Ajoutez ensuite l'appelant du résolveur d'assembly dans le Main:

public static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    .

... et ajoutez le résolveur lui-même quelque part dans la classe:

    static Assembly CurrentDomain_AssemblyResolve (expéditeur d'objet, arguments ResolveEventArgs)
    {
        String resourceName = new AssemblyName (args.Name) .Name + ".dll";

        utilisant (var stream = Assembly.GetExecutingAssembly (). GetManifestResourceStream (resourceName))
        {
            Byte [] assemblyData = new Byte [stream.Length];
            stream.Read (assemblyData, 0, assemblyData.Length);
            return Assembly.Load (assemblyData);
        }

    }

Je nomme le script vbs pour qu'il corresponde au nom du fichier .cs (par exemple, ssh.vbs recherche ssh.cs); cela rend l'exécution du script plusieurs fois beaucoup plus facile, mais si vous n'êtes pas un idiot comme moi, un script générique pourrait récupérer le fichier .cs cible à partir d'un glisser-déposer:

    Dim name_, oShell, fso
    Définissez oShell = CreateObject ("Shell.Application")
    Définissez fso = CreateObject ("Scripting.fileSystemObject")

    'PRENEZ LE NOM DU SCRIPT VBS COMME NOM DU FICHIER CIBLE
    '################################################
    name_ = Split (wscript.ScriptName, ".") (0)

    'OBTENEZ LES DLL EXTERNES ET LES NOMS DES ICÔNES DU FICHIER .CS
    «################################################# ######
    Const OPEN_FILE_FOR_READING = 1
    Définissez objInputFile = fso.OpenTextFile (name_ & ".cs", 1)

    'LISEZ TOUT DANS UN RÉSEAU
    «#############################
    inputData = Split (objInputFile.ReadAll, vbNewline)

    Pour chaque strData In inputData

        si laissé (strData, 7) = "// + ref>" alors 
            csc_references = csc_references & "/ reference:" & trim (replace (strData, "// + ref>", "")) & ""
        fin si

        si laissé (strData, 7) = "// + res>" alors 
            csc_resources = csc_resources & "/ resource:" & trim (replace (strData, "// + res>", "")) & ""
        fin si

        si laissé (strData, 7) = "// + ico>" alors 
            csc_icon = "/ win32icon:" & trim (replace (strData, "// + ico>", "")) & ""
        fin si
    Prochain

    objInputFile.Close


    «COMPILER LE FICHIER
    «################
    oShell.ShellExecute "c: \ windows \ microsoft.net \ framework \ v3.5 \ csc.exe", "/ warn: 1 / target: exe" & csc_references & csc_resources & csc_icon & "" & name_ & ".cs" , "", "runas", 2


    WScript.Quit (0)
Mark Llewellyn
la source
0

Il est possible, mais pas si simple, de créer un assemblage hybride natif / géré en C #. Si vous utilisiez C ++ à la place, ce serait beaucoup plus facile, car le compilateur Visual C ++ peut créer des assemblages hybrides aussi facilement que toute autre chose.

À moins que vous n'ayez une exigence stricte de produire un assemblage hybride, je suis d'accord avec MusiGenesis que cela ne vaut pas vraiment la peine d'être fait avec C #. Si vous devez le faire, envisagez plutôt de passer à C ++ / CLI.

Chris Charabaruk
la source
0

Généralement, vous auriez besoin d'une forme d'outil de post-construction pour effectuer une fusion d'assemblage comme vous le décrivez. Il existe un outil gratuit appelé Eazfuscator (eazfuscator.blogspot.com/) qui est conçu pour la manipulation de bytecode qui gère également la fusion des assemblys. Vous pouvez l'ajouter dans une ligne de commande de post-génération avec Visual Studio pour fusionner vos assemblys, mais votre kilométrage variera en raison de problèmes qui surviendront dans tous les scénarios de fusion d'assemblys non classiques.

Vous pouvez également vérifier si la construction fait de l'utilité NANT a la capacité de fusionner des assemblys après la construction, mais je ne connais pas assez bien NANT pour dire si la fonctionnalité est intégrée ou non.

Il existe également de nombreux plug-ins Visual Studio qui effectueront la fusion d'assembly dans le cadre de la création de l'application.

Alternativement, si vous n'avez pas besoin que cela soit fait automatiquement, il existe un certain nombre d'outils comme ILMerge qui fusionneront les assemblys .net en un seul fichier.

Le plus gros problème que j'ai rencontré avec la fusion d'assemblys est qu'ils utilisent des espaces de noms similaires. Ou pire, référencez différentes versions de la même dll (mes problèmes étaient généralement avec les fichiers dll NUnit).

wllmsaccnt
la source
1
Eazfuscator appellera simplement IlMerge, AFAIK.
Bobby
+1 Bobby. J'aurais dû m'en souvenir. A propos de tout ce que fait Eazfucator pour vous, vous résumez les appels réels à ILMerge avec un fichier de configuration plus général.
wllmsaccnt du