Pergunta

Eu tenho um problema semelhante, mas sutilmente diferente, ao descrito aqui (Carregando assemblies e suas dependências).

Eu tenho uma DLL C++ para renderização 3D que é o que vendemos aos clientes.Para usuários do .NET, teremos um wrapper CLR em torno dele.A DLL C++ pode ser construída em versões de 32 e 64 bits, mas acho que isso significa que precisamos ter dois wrappers CLR, já que o CLR se liga a uma DLL específica.

Digamos agora que nosso cliente tem um aplicativo .NET que pode ser de 32 ou 64 bits e, sendo um aplicativo .NET puro, deixa o CLR para resolvê-lo a partir de um único conjunto de assemblies.A questão é como o código do aplicativo pode escolher dinamicamente entre nossas combinações CLR/DLL de 32 e 64 bits em tempo de execução?

Ainda mais especificamente, a resposta sugerida para a questão acima mencionada também é aplicável aqui (ou seja,criar um manipulador ResolveEvent)?

Foi útil?

Solução

Finalmente tenho uma resposta para isso que parece funcionar.

Compile as versões de 32 e 64 bits - gerenciadas e não gerenciadas - em pastas separadas.Em seguida, faça com que o aplicativo .NET escolha em tempo de execução de qual diretório carregar os assemblies.

O problema de usar o ResolveEvent é que ele só é chamado se os assemblies não forem encontrados, então é muito fácil acabar acidentalmente com versões de 32 bits.Em vez disso, use um segundo objeto AppDomain onde podemos alterar a propriedade ApplicationBase para apontar para a pasta correta.Então você acaba com um código como:

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

  }

Você acaba com 2 exes - seu aplicativo normal e um segundo aplicativo de comutação que escolhe quais bits carregar.Observação: não posso receber o crédito pelos detalhes disso.Um dos meus colegas descobriu isso, dada a minha indicação inicial.Se e quando ele se inscrever no StackOverflow, atribuirei a resposta a ele

Outras dicas

Consegui fazer isso há cerca de um ano, mas não me lembro mais de todos os detalhes.Basicamente, você pode usar IntPtr.Size para determinar qual DLL carregar e, em seguida, executar o LoadLibrary real por meio de p/Invoke.Nesse ponto, você tem o módulo na memória e deve ser capaz de apenas p/Invoke funções de dentro dele - o mesmo nome do módulo não deve ser recarregado novamente.

Acho, porém, que em meu aplicativo eu realmente fiz com que a DLL C++ se registrasse como um servidor COM e, em seguida, acessasse sua funcionalidade por meio de um wrapper .NET gerado - então não sei se já testei p/Invoking diretamente.

Encontrei um cenário semelhante há algum tempo.Um kit de ferramentas que eu estava usando não se comportou bem em um ambiente de 64 bits e não consegui encontrar uma maneira de forçar dinamicamente os assemblies a se vincularem como 32 bits.

É possível forçar seus assemblies a funcionarem no modo 32 bits, mas isso requer correção do cabeçalho CLR (existe uma ferramenta que faz isso no Framework) e se seus assemblies tiverem nomes fortes, isso não funciona.

Receio que você precise criar e publicar dois conjuntos de binários para plataformas de 32 e 64 bits.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top