Domanda

Ho un problema simile a quello descritto, ma leggermente diverso da quello descritto Qui (Caricamento degli assembly e relative dipendenze).

Ho una DLL C++ per il rendering 3D che è ciò che vendiamo ai clienti.Per gli utenti .NET avremo un wrapper CLR attorno ad esso.La DLL C++ può essere creata sia nella versione a 32 che a 64 bit, ma penso che questo significhi che dobbiamo avere due wrapper CLR poiché CLR si lega a una DLL specifica?

Supponiamo ora che il nostro cliente abbia un'app .NET che può essere a 32 o 64 bit e che essendo un'app .NET pura lascia che sia CLR a elaborarla da un singolo set di assembly.La domanda è: come può il codice dell'app scegliere dinamicamente tra le nostre combinazioni CLR/DLL a 32 e 64 bit in fase di esecuzione?

Ancora più specificatamente, anche in questo caso è applicabile la risposta suggerita alla suddetta domanda (i.e.creare un gestore ResolveEvent)?

È stato utile?

Soluzione

Finalmente ho una risposta che sembra funzionare.

Compila entrambe le versioni a 32 e 64 bit, sia gestite che non gestite, in cartelle separate.Chiedi quindi all'app .NET di scegliere in fase di esecuzione da quale directory caricare gli assembly.

Il problema con l'utilizzo di ResolveEvent è che viene chiamato solo se non vengono trovati assembly, quindi è fin troppo facile ritrovarsi accidentalmente con versioni a 32 bit.Utilizza invece un secondo oggetto AppDomain in cui possiamo modificare la proprietà ApplicationBase in modo che punti alla cartella giusta.Quindi ti ritroverai con un codice come:

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

  }

Alla fine ti ritroverai con 2 ex: la tua app normale e una seconda app di commutazione che sceglie quali bit caricare.Nota: non posso prendermi il merito per i dettagli di questo personalmente.Uno dei miei colleghi lo ha capito grazie al mio suggerimento iniziale.Se e quando si iscriverà a StackOverflow gli assegnerò la risposta

Altri suggerimenti

Ho potuto farlo circa un anno fa, ma non ricordo più tutti i dettagli.Fondamentalmente, puoi utilizzare IntPtr.Size per determinare quale DLL caricare, quindi eseguire l'effettivo LoadLibrary tramite p/Invoke.A quel punto, hai il modulo in memoria e dovresti essere in grado di eseguire semplicemente le funzioni p/Invoke dal suo interno: lo stesso nome del modulo non dovrebbe essere ricaricato di nuovo.

Penso, tuttavia, che nella mia applicazione la DLL C++ si registrasse come server COM e quindi accedessi alle sue funzionalità tramite un wrapper .NET generato, quindi non so se ho mai testato direttamente p/Invoking.

Ho riscontrato uno scenario simile qualche tempo fa.Un toolkit che stavo utilizzando non si comportava bene in un ambiente a 64 bit e non sono riuscito a trovare un modo per forzare dinamicamente il collegamento degli assembly a 32 bit.

È possibile forzare i tuoi assembly a funzionare in modalità a 32 bit, ma ciò richiede l'applicazione di patch all'intestazione CLR (esiste uno strumento che lo fa nel Framework) e se i tuoi assembly hanno nomi forti, questo non funziona.

Temo che dovrai creare e pubblicare due set di binari per piattaforme a 32 e 64 bit.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top