Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
[erledigt] AssemblyResolve - einbinden dlls in die exe
Amosius
myCSharp.de - Member



Dabei seit:
Beiträge: 31

Themenstarter:

[erledigt] AssemblyResolve - einbinden dlls in die exe

beantworten | zitieren | melden

Über den Artikel von Jeffrey Richter (hier der Artikel) bin ich auf die AssemblyResolve-Variante für meine Anliegen gestossen.
Habe die Historie des Forums und etliche Google Anfragen gestartet, leider ohne Erfolg. Vielleicht könnt ihr mir einen Rat geben:

Ich möchte gerne diverse Dlls von Drittanbietern in eine EXE einer WPF-Anwendung integrieren, analog dem oben genannten Artikel. Hierzu soll die DLL in die EXE eingebunden werden und durch das AssemblyResolve Event gefunden werden.

Meine Vorgehensweise:
Ich habe zusätzlich zum Verweis der DLL die Dll selbst zum Projekt hinzugefügt (hinzufügen -> vorhandenes Element) und den Build-Vorgang auf eingebettete Ressource umgestellt.

Folgenden Code habe ich verwendet:

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Simple
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {

            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {

                String resourceName = "AssemblyLoadingAndReflection." +

                   new AssemblyName(args.Name).Name + ".dll";

                using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                {

                    Byte[] assemblyData = new Byte[stream.Length];

                    stream.Read(assemblyData, 0, assemblyData.Length);

                    return Assembly.Load(assemblyData);

                }

            };

            InitializeComponent();



            Test();

        }

        private void Test()
        {
            DLLClass Test = new DLLClass(); //hierzu ist die DLL notwendig
        }

    }
}

Ich bin mir nicht sicher ob die Position von AssemblyRessolve in dieser WPF-Anwendung die richtige ist. Zumindest wird diese ausgeführt, bevor
das Testobject initiiert wird.

Nun gehe ich in mein Debugverzeichnis und lösche die DLL, die das Programm ja benötigt. Die Anwendung kann ohne die DLL nicht ordnungsgemäß gestartet werden, obwohl ich an der Dateigröße der EXE sehe, dass die dll integriert sein muss.

Ich nehme an, dass ich das AssemblyResolve Event woanders hinterlegen muss?

Bin für Hinweise dankbar.

Amosius
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Amosius am .
private Nachricht | Beiträge des Benutzers
JuyJuka
myCSharp.de - Experte

Avatar #avatar-2316.jpg


Dabei seit:
Beiträge: 2.187
Herkunft: Deutschland

beantworten | zitieren | melden

Hallo Amosius,

Dazu gibt es schon ein fertiges Programm, welches alles notwendige in deiner fertigen (normalen) Anwendung einbindet.
.Netz

Gruß
Juy Juka
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von JuyJuka am .
private Nachricht | Beiträge des Benutzers
Amosius
myCSharp.de - Member



Dabei seit:
Beiträge: 31

Themenstarter:

beantworten | zitieren | melden

Hallo JuyJuka,

vielen Dank, probiere ich aus.

Weiterhin würde ich gerne auch mal mein oberes Beispiel zum Laufen bringen.
Eine Idee woran das liegt?

Viele Grüße,
Amosius
private Nachricht | Beiträge des Benutzers
DFDotNet
myCSharp.de - Member



Dabei seit:
Beiträge: 201

beantworten | zitieren | melden

Zitat von Amosius
Ich nehme an, dass ich das AssemblyResolve Event woanders hinterlegen muss?
Amosius

Denke ich auch, denn im Artikel steht ja:
Zitat von "Jeffrey Richter"
when your application initializes, register a callback method with the AppDomain’s ResolveAssembly event

Darum würde ich es mal so probieren (nicht im Window, sondern in der Application):


  /// <summary>
  /// Interaktionslogik für "App.xaml"
  /// </summary>
  public partial class App : Application
  {
    public App()
    {
      AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
      {
        String resourceName = "AssemblyLoadingAndReflection." +
           new AssemblyName(args.Name).Name + ".dll";

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

Gruß
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von DFDotNet am .
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1.361
Herkunft: Berlin

beantworten | zitieren | melden

Hi,
Zitat von DFDotNet
Zitat von Richter
when your application initializes, register a callback method with the AppDomain’s ResolveAssembly event

Darum würde ich es mal so probieren (nicht im Window, sondern in der Application):

Ich würde es nicht im Konstruktor ("public App(){...}") definieren, sondern im Typinitialisierer ("static App(){...}").

beste Grüße
zommi
private Nachricht | Beiträge des Benutzers
JuyJuka
myCSharp.de - Experte

Avatar #avatar-2316.jpg


Dabei seit:
Beiträge: 2.187
Herkunft: Deutschland

beantworten | zitieren | melden

Hallo,

Um sich am AssemblyResolve-Ereigniss anzumelden gibt es eigentlich nur eine gute stelle, wenn man die *.exe selber schreibt:
Die ersten 5 Zeilen in der Main-Methode.

Schreibt man nur eine Komponente die von anderen Geladen wird, dann muss man in jeder öffentlichen Klasse einen Typinitialisierer schreiben und dort eine Methode aufrufen, die das Anmelden übernimmt (und dafür sorgt, dass man sich nur einmal anmeldet).

Gruß
Juy Juka
private Nachricht | Beiträge des Benutzers
Amosius
myCSharp.de - Member



Dabei seit:
Beiträge: 31

Themenstarter:

beantworten | zitieren | melden

Hallo,

vielen Dank für die Antworten.
Die Anwendung .Netz habe ich auf mein .NET Framework kompiliert. Leider war die Anwendung nach dem Zusammenfügen nicht mehr ganz die gleiche (Icons in der Anwendung waren verschwunden...).

ich habe aus Komfortgünden die folgende Funktion in die App.xaml.cs eingefügt,
die mir bei jedem kompilieren direkt eine fertige Executable erstellt:

        static App()
        {
            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                Console.WriteLine(new System.Reflection.AssemblyName(args.Name).Name);


                String resourceName = "MeinAnwendungsname." +

                    new System.Reflection.AssemblyName(args.Name).Name + ".dll";

                using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                {

                    Byte[] assemblyData = new Byte[stream.Length];

                    stream.Read(assemblyData, 0, assemblyData.Length);

                    return System.Reflection.Assembly.Load(assemblyData);

                }

            };
        }       

Den Beitrag schliesse ich. Vielen Dank nochmals.
private Nachricht | Beiträge des Benutzers