Pergunta

Estou ficando System.IO.FileNotFoundException: The specified module could not be found ao executar código C # que chama um C ++ / CLI montagem que por sua vez chama um puro C DLL. Acontece assim que um objeto é instanciado que chama a puros funções C DLL.

BackingStore é puro C. CPPDemoViewModel é C ++ / CLI chamar BackingStore tem uma referência a BackingStore.

Eu tentei o caso mais simples possível - adicionar um novo projeto de teste de unidade C # que apenas tenta criar um objeto definido no CPPDemoViewModel. Eu adicionei uma referência do projeto C # para CPPDemoViewModel.

projeto de teste ++ / CLI A C fina funciona apenas com a ref adicionado ao CPPDemoViewModel por isso é algo sobre ir entre os idiomas.

Estou usando o Visual Studio 2008 SP1 com .Net 3.5 SP1. Estou construindo no Vista x64, mas ter o cuidado de garantir que a minha meta Platform está definido para x86.

Isto parece algo estúpido e óbvio que estou em falta, mas seria ainda mais estúpido da minha parte de perder tempo a tentar resolvê-lo em privado, então eu estou aqui fora envergonhando-me!

Este é um teste para um projeto de portar uma quantidade enorme de código legado C que eu estou mantendo em um DLL com um ViewModel implementado em C ++ / CLI.

Editar Depois de verificar diretórios, posso confirmar que o BackingStore.dll não foi copiado.

Eu tenho as pastas projecto único padrão criados com uma solução típica multi-projeto.

WPFViewModelInCPP
  BackingStore
  CPPViewModel
  CPPViewModelTestInCS
    bin
      Debug
  Debug

O alto nível de depuração parece ser uma pasta comum usado pelos projetos C e C ++ / CLI, para minha surpresa.

WPFViewModelInCPP \ Debug contém BackingStore.dll, CPPDemoViewModel.dll, CPPViewModelTest.dll e sua .ilk associado e ficheiros.pdb

WPFViewModelInCPP \ CPPViewModelTestInCS \ bin \ Debug contém CPPDemoViewModel e CPPViewModelTestInCS .dll e ficheiros.pdb mas não BackingStore. No entanto, copiando manualmente BackingStore para o diretório não corrigir o erro.

CPPDemoViewModel tem a propriedade Copy Local set que eu suponho que é responsável por copiar seu DLL quando se é referenciado. Eu não posso adicionar uma referência de um projeto C # para um puro C DLL -. Ele apenas diz uma referência para Fazendo loja não pode ser adicionado

Eu não tenho certeza se eu tiver apenas um problema ou dois.

Eu posso usar uma etapa de cópia de construção antiquada para copiar o BackingStore.dll em diretórios qualquer projeto C #, embora eu esperava o novo modelo .net não exigia isso.

DependencyWalker está me dizendo que o arquivo que está faltando é GPSVC.dll que foi sugerido indica problemas de configuração de segurança. Eu suspeito que este é um arenque vermelho.

edit2 Com uma cópia manual dos BackingStore.dll estar ao lado do executável, a GUI agora funciona bem. O Projeto # Teste C ainda tem problemas que eu suspeito é devido ao ambiente de tempo de execução de um projeto de teste, mas eu posso viver sem isso por enquanto.

Foi útil?

Solução 2

A resposta para a GUI, além de alterar as configurações de saída, foi a adição de um pré-compilação Passo

copy $(ProjectDir)..\Debug\BackingStore.* $(TargetDir)

A resposta para os projetos de teste foi para adicionar a DLL ausente para a guia de implantação do testrunconfig. Você pode fazê-lo editando diretamente o padrão LocalTestRun.testrunconfig (aparece no Solution sob Solution Items) ou clique com o botão direito do mouse na solução e adicionar uma nova configuração de execução de teste, que irá aparecer sob o teste principal menu.

Obrigado pelas respostas sobre esta pergunta SO em configurações de teste para me levando à resposta.

Outras dicas

As DLLs C e C ++ no mesmo diretório como o C # montagem que de execução?

Você pode ter que alterar as configurações de saída do projeto para que o C # montagem e as outras DLLs todos acabam na mesma pasta.

Eu sempre usei o Dependency Walker em casos como este; é uma verificação de sanidade que mostra que todas as dependências pode realmente ser encontrados.

Uma vez que o aplicativo está sendo executado, você também pode querer experimentar Process Monitor sobre o código que você está correndo, para ver quais DLLs estão sendo referenciado, e onde eles estão localizados.

A razão pela qual isso acontece é porque você quer são carregamento DllMain do código gerenciado, antes da CRT tem a oportunidade de ser inicializado. Você pode não ter qualquer código gerenciado, ser executado DIRETAMENTE ou INDERECTLY de um efeito de notificações DllMain. . (Veja: Especialista C ++ / CLI: .Net para o Visual C ++ Programmers, capítulo 11 ++)

Ou você não tem entrypoint nativa definida wahtsoever, ainda que você tenha ligado a MSVCRT. O CLR é inicializado automaticamente para você com / clr, esse detalhe faz com que um monte de confusão e deve ser levado em conta. Um modo de DLL misto realmente cargas de atraso o CLR através do uso de hot-patching todos os vtables ponto de entrada gerenciados em suas classes.

Uma série de questões de inicialização classe rodeiam este tema, bloqueio do carregador e demora carregamento CLR são um pouco trickey às vezes. Tentar declarar estática do global e não use # pragma gerenciado /, isolar o código com / clr por arquivo.

Se você não pode isolar o código a partir do código gerenciado, e estão tendo problemas, (depois de tomar algumas dessas etapas), você também pode olhar para a hospedagem do CLR si mesmo e talvez a atravessar o esforço de criar um gerenciador de domínio, que asseguraria o seu totalmente "in-the-loop" de eventos de tempo de execução e bootstrapping.

Esta é exactally por isso, tem nothting TODO com o seu caminho de busca, ou inicialização. Infelizmente, o visualizador de log Fusão não ajuda muito (que é o lugar habitual de olhar para .NET CLR problemas de montagem de ligação não dependência walker).

Linking estaticamente tem TODO nada com isso também. Você pode não estaticamente vincular um ++ / CLI aplicativo C que é o modo misto.

  1. Posicione a função DllMain em um arquivo por si só.
  2. Certifique-se de que este arquivo faz não Have / CLR set nas opções de compilação ( arquivo opções de compilação)
  3. Verifique se o seu ligando com / MD ou / MDd, e todas as suas dependências que você vincular usar exatamente a mesma CRT.
  4. Avaliar as configurações do vinculador para / DEFAULTLIB e / include para identificar quaisquer problemas de referência possiable, você pode declarar um protótipo no seu código e uso / include para substituir resolução link da biblioteca padrão.

Boa sorte, também verificar que o livro é muito bom.

Este é um dilema interessante. Eu nunca ouvi falar de um problema ao carregar DLLs nativas C ++ / CLI após uma chamada para ele a partir de C # antes. Só posso supor que o problema é como @ Daniel L sugeriu, e que sua DLL simplesmente não está em um caminho o carregador de montagem pode encontrar.

Se a sugestão de Daniel não der certo, eu sugiro que você tente ligar estaticamente o código C nativo para o C ++ / programa CLI, se você puder. Isso certamente resolver o problema, como a DLL seria então inteiramente absorvido no C ++ / CLI DLL.

Verifique se o sistema de destino tem o MS corretas Visual C tempo de execução, e que você não está acidentalmente criar a DLL C com um tempo de execução de depuração.

teve o mesmo problema de mudar para 64-bit Vista. Nosso aplicativo foi chamado Win32 DLLs que estava confundindo o build-alvo para a aplicação. Para resolver isso, fizemos o seguinte:

  1. Vá para propriedades do projeto;
  2. Escolha um guia Construir;
  3. Alterar 'target Plataforma:' opção para x86;
  4. Reconstruir a aplicação.

Quando eu re-correu a aplicação funcionou.

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