712 Stimmen

Einbetten von DLLs in eine kompilierte ausführbare Datei

Ist es möglich, eine bereits existierende DLL in eine kompilierte C#-Datei einzubetten (so dass Sie nur eine Datei zu verteilen haben)? Wenn es möglich ist, wie würde man dabei vorgehen?

Normalerweise bin ich damit einverstanden, die DLLs einfach draußen zu lassen und das Setup-Programm alles erledigen zu lassen, aber es gab ein paar Leute bei der Arbeit, die mich danach gefragt haben, und ich weiß es ehrlich gesagt nicht.

18voto

Marcell Toth Punkte 2901

.NET Core 3.0 unterstützt von Haus aus die Kompilierung zu einer einzigen .exe

Die Funktion wird durch die Verwendung der folgenden Eigenschaft in Ihrer Projektdatei (.csproj) aktiviert:

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

Dies geschieht ohne ein externes Werkzeug.

Siehe meine Antwort für diese Frage für weitere Einzelheiten.

17voto

Steve Punkte 1442

Le site Auszug von Jeffrey Richter ist sehr gut. Kurz gesagt, fügen Sie die Bibliothek als eingebettete Ressourcen und fügen Sie einen Rückruf vor alles andere. Hier ist eine Version des Codes (gefunden in den Kommentaren seiner Seite), die ich am Anfang der Main-Methode für eine Konsolenanwendung einfüge (stellen Sie einfach sicher, dass alle Aufrufe, die die Bibliotheken verwenden, in einer anderen Methode als Main sind).

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);
            }
        };

15voto

Josh Punkte 667

Zur Erweiterung der @Bobby's asnwer oben. Sie können Ihre .csproj so bearbeiten, dass Sie IL-Repack um alle Dateien automatisch in eine einzige Baugruppe zu packen, wenn Sie bauen.

  1. Installieren Sie das nuget ILRepack.MSBuild.Task-Paket mit Install-Package ILRepack.MSBuild.Task
  2. Bearbeiten Sie den Abschnitt AfterBuild Ihres .csproj

Hier ist ein einfaches Beispiel, das ExampleAssemblyToMerge.dll in Ihre Projektausgabe einfügt.

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

12voto

Ludovic Feltz Punkte 10775

Die folgende Methode KEINE externen Werkzeuge verwenden et AUTOMATISCH alle benötigten DLLs einbinden (keine manuellen Maßnahmen erforderlich, alles wird bei der Kompilierung erledigt)

Ich habe hier viele Antworten gelesen, die besagen, dass man die ILMerge , ILRepack o Jeffrey Ritcher Methode, aber nichts davon funktionierte mit WPF-Anwendungen noch einfach zu bedienen war.

Wenn Sie viele DLLs haben, kann es schwierig sein, die benötigten DLLs manuell in Ihre Exe einzubinden. Die beste Methode, die ich gefunden habe, wurde von Wegged erklärt hier auf StackOverflow

Der Klarheit halber habe ich seine Antwort hierher kopiert (alle Anerkennung an Wegged )


1) Fügen Sie dies zu Ihrem .csproj Datei:

<Target Name="AfterResolveReferences">
  <ItemGroup>
    <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
      <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
    </EmbeddedResource>
  </ItemGroup>
</Target>

2) Machen Sie Ihr Main Program.cs sehen so aus:

[STAThreadAttribute]
public static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
    App.Main();
}

3) Fügen Sie die OnResolveAssembly Methode:

private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    AssemblyName assemblyName = new AssemblyName(args.Name);

    var path = assemblyName.Name + ".dll";
    if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);

    using (Stream stream = executingAssembly.GetManifestResourceStream(path))
    {
        if (stream == null) return null;

        var assemblyRawBytes = new byte[stream.Length];
        stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
        return Assembly.Load(assemblyRawBytes);
    }
}

9voto

Nathan Punkte 12210

Ein weiteres Produkt, das dies auf elegante Weise bewerkstelligen kann, ist SmartAssembly, unter SmartAssembly.de . Dieses Produkt fasst nicht nur alle Abhängigkeiten in einer einzigen DLL zusammen, sondern verschleiert (optional) auch Ihren Code, entfernt zusätzliche Metadaten, um die resultierende Dateigröße zu verringern, und kann auch die AWL optimieren, um die Laufzeitleistung zu erhöhen.

Es gibt auch eine Art globaler Ausnahmebehandlungs-/Berichterstattungsfunktion, die Ihrer Software hinzugefügt wird (falls gewünscht) und die nützlich sein könnte. Ich glaube, es hat auch eine Befehlszeilen-API, so dass Sie es zu einem Teil Ihres Build-Prozesses machen können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X