Frage

Ich habe ein ähnliches, aber geringfügig anderes Problem als das beschriebene Hier (Laden von Baugruppen und ihren Abhängigkeiten).

Ich habe eine C++-DLL für 3D-Rendering, die wir an Kunden verkaufen.Für .NET-Benutzer werden wir einen CLR-Wrapper darum herum haben.Die C++-DLL kann sowohl in der 32- als auch in der 64-Bit-Version erstellt werden, aber ich denke, das bedeutet, dass wir zwei CLR-Wrapper benötigen, da die CLR an eine bestimmte DLL bindet?

Angenommen, unser Kunde hat eine .NET-App, die entweder 32 oder 64 Bit sein kann, und da es sich um eine reine .NET-App handelt, muss die CLR sie aus einem einzigen Satz von Assemblys berechnen.Die Frage ist, wie der App-Code zur Laufzeit dynamisch zwischen unseren 32- und 64-Bit-CLR/DLL-Kombinationen wählen kann.

Genauer gesagt gilt die vorgeschlagene Antwort auf die oben genannte Frage auch hier (d. h.einen ResolveEvent-Handler erstellen)?

War es hilfreich?

Lösung

Endlich habe ich eine Antwort darauf, die zu funktionieren scheint.

Kompilieren Sie sowohl die 32- als auch die 64-Bit-Version – sowohl die verwaltete als auch die nicht verwaltete – in separaten Ordnern.Lassen Sie dann die .NET-App zur Laufzeit auswählen, aus welchem ​​Verzeichnis die Assemblys geladen werden sollen.

Das Problem bei der Verwendung von ResolveEvent besteht darin, dass es nur dann aufgerufen wird, wenn keine Assemblys gefunden werden, sodass es nur allzu leicht passieren kann, dass man versehentlich 32-Bit-Versionen erhält.Verwenden Sie stattdessen ein zweites AppDomain-Objekt, bei dem wir die ApplicationBase-Eigenschaft so ändern können, dass sie auf den richtigen Ordner zeigt.Am Ende erhalten Sie Code wie:

static void Main(String[] argv)
  {
     // Create a new AppDomain, but with the base directory set to either the 32-bit or 64-bit
     // sub-directories.

     AppDomainSetup objADS = new AppDomainSetup();

     System.String assemblyDir = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
     switch (System.IntPtr.Size)
     {
        case (4): assemblyDir += "\\win32\\";
           break;
        case (8): assemblyDir += "\\x64\\";
           break;
     }

     objADS.ApplicationBase = assemblyDir;

     // We set the PrivateBinPath to the application directory, so that we can still
     // load the platform neutral assemblies from the app directory.
     objADS.PrivateBinPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);

     AppDomain objAD = AppDomain.CreateDomain("", null, objADS);
     if (argv.Length > 0)
        objAD.ExecuteAssembly(argv[0]);
     else
        objAD.ExecuteAssembly("MyApplication.exe");

     AppDomain.Unload(objAD);

  }

Am Ende haben Sie zwei Exes – Ihre normale App und eine zweite Switching-App, die auswählt, welche Bits geladen werden sollen.Hinweis: Ich kann die Details hierzu nicht selbst übernehmen.Einer meiner Kollegen hat das aufgrund meines ersten Hinweises herausgefunden.Wenn er sich bei StackOverflow anmeldet, werde ich ihm die Antwort zuweisen

Andere Tipps

Das ist mir vor etwa einem Jahr gelungen, aber ich erinnere mich nicht mehr an alle Details.Grundsätzlich können Sie IntPtr.Size verwenden, um zu bestimmen, welche DLL geladen werden soll, und dann die eigentliche LoadLibrary über p/Invoke ausführen.An diesem Punkt haben Sie das Modul im Speicher und sollten in der Lage sein, darin einfach p/Invoke-Funktionen auszuführen – derselbe Modulname sollte nicht erneut geladen werden.

Ich glaube jedoch, dass ich in meiner Anwendung die C++-DLL tatsächlich selbst als COM-Server registrieren ließ und dann über einen generierten .NET-Wrapper auf ihre Funktionalität zugegriffen habe – ich weiß also nicht, ob ich p/Invoking jemals direkt getestet habe.

Ich bin vor einiger Zeit auf ein ähnliches Szenario gestoßen.Ein von mir verwendetes Toolkit verhielt sich in einer 64-Bit-Umgebung nicht gut und ich konnte keine Möglichkeit finden, die Assemblys dynamisch zur Bindung als 32-Bit-Umgebung zu zwingen.

Es ist möglich, die Arbeit Ihrer Assemblys im 32-Bit-Modus zu erzwingen. Dazu ist jedoch ein Patchen des CLR-Headers erforderlich (im Framework gibt es ein Tool, das dies erledigt), und wenn Ihre Assemblys einen starken Namen haben, funktioniert dies nicht.

Ich fürchte, Sie müssen zwei Sätze Binärdateien für 32- und 64-Bit-Plattformen erstellen und veröffentlichen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top