Wie kann ich .NET zwingen, eine lokale Kopie einer Assembly zu verwenden, die sich im GAC befindet?

70

Ich habe eine .NET - Assembly , dass (aus Gründen außerhalb meiner Kontrolle) muss im GAC sein. Dieselbe Assembly wird jedoch von einem anderen Programm verwendet, das über eine eigene Kopie einer älteren Version derselben Assembly verfügt. Es muss eine eigene Kopie verwenden und nicht das, was sich im GAC befindet. Die richtige Versionierung ist in diesem Fall wahrscheinlich mühsamer als es sich lohnt, aus Gründen, auf die ich nicht eingehen werde. Meine Fragen sind: Gibt es sowieso etwas zu sagen .NET: Verwenden Sie einfach DIESE DLL, genau hier in diesem Verzeichnis - ignorieren Sie alles, was Sie im GAC oder anderswo finden .

EMP
quelle

Antworten:

46

Stellen Sie sicher, dass die GAC-Assembly und die lokale Assembly unterschiedliche Versionsnummern haben (keine schlechte Idee, Ihre Build-Nummer zumindest automatisch inkrementieren zu lassen, indem Sie Ihre AssemblyVersion in AssemblyInfo: [Assembly: AssemblyVersion ("1.0.0. *") Mit einem Platzhalter versehen. )]). Leiten Sie dann Ihre Assembly-Bindung mithilfe der Konfiguration Ihrer App um:

In Ihrem Fall benötigen Sie das Attribut "applyTo" der AssemblyBinding-Konfiguration nicht. Sie brauchen nur so etwas wie:

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="YourAssembly" publicKeyToken="AAAAAAAAAAAA" culture="neutral"/>
            <bindingRedirect oldVersion="0.0.0.0-5.2.1.0" newVersion="5.0.8.1"/>
        </dependentAssembly>
    </assemblyBinding>
</runtime>
Corbin März
quelle
3
Können Sie diese Bindungsumleitung vermeiden, indem Sie die App neu kompilieren, um die neue Version der DLL zu verwenden, oder ist immer eine Konfigurationsänderung erforderlich?
Dan
Wenn Sie den Revisionsteil Ihrer Versionsnummer auf einstellen, wird *diese nicht automatisch erhöht. Die MSDN-Dokumentation zu AssemblyVersionAttribute gibt an, dass es zufällig sein sollte, aber in der Praxis verwendet Visual Studio die Anzahl der Sekunden seit Mitternacht geteilt durch 2.
M. Dudley
Sie sagen also, dass jede Assembly bei jedem Build neu versioniert wird, auch wenn keine Änderungen vorgenommen wurden, damit wir die Abhängigkeit von GAC aufheben können. Wozu dient die Assembly Binding Redirect? Das einzige, woran ich denken kann, ist, dass es für Produkte verwendet werden kann. Wenn Ihr Projekt in GAC auf 5.0.8.3453 anstelle von 5.0.8.1 verweist, nur weil Sie es auf dev ohne Änderungen neu versioniert haben, wird es dies sein umgeleitet auf 5.0.8.1. Ist das richtig? Klobig, aber ich sehe keinen anderen Weg, um das zu umgehen.
Sergey Akopov
1
Ich bin verwirrt. Dieser Artikel sagt, dass es möglich ist aip.im/2013/04/…
Niloofar
31

Wenn sie die gleiche Versionsnummer haben, ist die Antwort, dass Sie nicht können. Wenn Sie versuchen, eine Assembly zu laden, die denselben vollständigen Assemblynamen (Name, Version, Schlüssel) wie eine GAC-Assembly hat, wählt die CLR jedes Mal die GAC-Assembly aus.

JaredPar
quelle
1
Ich weiß nicht, wer das abgelehnt hat, aber ich erlebe das Gleiche wie @JaredPar und es macht mich verrückt. Es wird vom GAC geladen. Ich habe zwei Assemblys mit demselben vollständigen Namen und möchte meine leicht modifizierte laden. PITA-BROT.
Csaba Toth
hast du das versucht aip.im/2013/04/…
Niloofar
Sie können die DLL mit DNSPY so ändern, dass sie eine andere Signatur und Version hat. Ein bisschen hackisch, aber es wird funktionieren.
rollt
@rolls Wie kann ich die Assembly-Version mit dnspy ​​ändern? Ich habe versucht, die Version zu ändern, aber nach dem Kompilieren wird nur die ursprüngliche Version verwendet. Übrigens: Ich überprüfe die Version, indem ich mit der rechten Maustaste auf die Registerkarte Eigenschaften und Details klicke.
Ozkan
Haben Sie das Speichermodul verwendet? Überprüfen Sie dort auch alle Optionen. Es ist definitiv möglich, das zu tun, was ich zuvor erfolgreich getan habe.
rollt
10

Sie können DEVPATH so einstellen, dass das Laden einer Baugruppe erzwungen wird (siehe Linktext)

Dies beantwortet Ihre Frage nicht, da es nur für Entwicklungszwecke gedacht ist und selbst dann nicht wirklich empfohlen wird, da es nicht die Produktionsnutzung widerspiegelt. Ich dachte jedoch, ich werde es trotzdem teilen, da es gut zu wissen ist.

Ying
quelle
2

Haben Sie Assembly.LoadFromFile () ausprobiert? Dies ist eine manuelle Aufgabe, sollte jedoch Ihre Baugruppe in den Speicher laden, bevor sie benötigt wird. .NET verwendet dann die im Speicher, anstatt danach zu suchen.

Ein anderer Weg wäre, wenn die lokale Versammlung nicht signiert wäre, könnten Sie es auf diese Weise unterscheiden.

rauben

Robert Wagner
quelle
4
Gute Idee, aber nein, es funktioniert nicht - LoadFile () lädt die richtige Assembly, aber wenn die referenzierte Assembly verwendet wird, wird sie trotzdem vom GAC geladen. :(
EMP
2
Es gibt keine verwaltete Möglichkeit, eine lokale Kopie einer GAC-Assembly zu laden
JaredPar
Verwenden Sie dnspy, um die Signatur und Version der DLL zu ändern. Anschließend können Sie das Laden Ihrer benutzerdefinierten gehackten DLL erzwingen.
rollt
2

Ich hatte ein ähnliches Problem. Ich habe das publicKeyToken der Ziel-DLL geändert, indem ich eine neue DLL verwendet ildasmund ilasmgeneriert habe. Ich habe es dann in der Projektreferenz aktualisiert, um auf die neue DLL zu verweisen. Die Schritte, die ich unternommen habe, sind hier .

Das hat bei mir funktioniert.

Dasons
quelle
1

Ein Grund dafür, dass die Bindungsumleitung nicht funktioniert, ist, dass der Oracle.ManagedDataAccess-Anbieter eine andere Suchreihenfolge für DLLs hat als der nicht verwaltete Anbieter. Der nicht verwaltete Anbieter startet im Anwendungsverzeichnis und sucht dann im DLL-Pfad in der Registrierung, dann im DLL-Pfad in machine.config und dann im DLL-Pfad in web.config. Gemäß der Oracle-Dokumentation funktioniert die Suchreihenfolge für den verwalteten Anbieter folgendermaßen:

Der verwaltete Treiber verweist auf diese Assemblys in der folgenden Suchreihenfolge:

  1. Globaler Assembly-Cache
  2. Das bin-Verzeichnis der Webanwendung oder das EXE-Verzeichnis der Windows-Anwendung
  3. Das Unterverzeichnis x86 oder x64 basiert darauf, ob die Anwendung in 32-Bit- oder 64-Bit-.NET Framework ausgeführt wird. Wenn die Anwendung mit AnyCPU erstellt wird, verwendet ODP.NET die richtige DLL-Bitness, solange die Assembly verfügbar ist. Oracle empfiehlt, diese Methode zum Suchen abhängiger Assemblys zu verwenden, wenn Ihre Anwendung AnyCPU ist.

https://docs.oracle.com/de/database/oracle/oracle-database/12.2/odpnt/installODPmd.html#GUID-0E834EC7-21DF-4913-B712-2B0A07FD58FD

Um dieses Problem zu beheben, müssen Sie die Registrierung der GAC-Assembly aufheben oder einfach eine andere Version von Oracle.ManagedDataAccess in Ihre bin und web.config einfügen als die in GAC, wenn Sie sie nicht deinstallieren können.

Charles Owen
quelle