C#到C++/CLI到C DLL System.IO.FileNotFoundException

C#到C++/CLI到C DLL System.IO.FileNotFoundException,c#,build-process,c++-cli,unmanaged,C#,Build Process,C++ Cli,Unmanaged,我得到System.IO.FileNotFoundException:运行调用C++/CLI程序集的C#代码时找不到指定的模块,而C++/CLI程序集又调用纯C DLL。一旦实例化了调用纯C DLL函数的对象,就会发生这种情况 BackingStore是纯C。 CPPDemoViewModel是调用BackingStore的C++/CLI,它引用了BackingStore 我尝试了最简单的情况——添加一个新的C#单元测试项目,该项目只尝试创建在CPPDemoViewModel中定义的对象。我在C

我得到
System.IO.FileNotFoundException:运行调用C++/CLI程序集的C#代码时找不到指定的模块,而C++/CLI程序集又调用纯C DLL。一旦实例化了调用纯C DLL函数的对象,就会发生这种情况

BackingStore是纯C。 CPPDemoViewModel是调用BackingStore的C++/CLI,它引用了BackingStore

我尝试了最简单的情况——添加一个新的C#单元测试项目,该项目只尝试创建在CPPDemoViewModel中定义的对象。我在CPPDemoViewModel中添加了一个来自C#项目的引用

C++/CLI测试项目只需将ref添加到CPPDemoViewModel中就可以正常工作,因此需要在两种语言之间切换

我正在使用VisualStudio2008SP1和.NET3.5SP1。我在Vista x64上构建,但一直小心地确保我的平台目标设置为x86

这感觉很愚蠢,很明显我错过了一些东西,但如果我浪费时间试图私下解决它,那就更愚蠢了,所以我在这里让自己难堪

这是对一个移植了大量遗留C代码的项目的测试,我将这些代码保存在一个DLL中,并在C++/CLI中实现了一个ViewModel

编辑 检查目录后,我可以确认BackingStore.dll没有被复制

我使用典型的多项目解决方案创建了标准的独特项目文件夹

WPFViewModelInCPP BackingStore CPPViewModel CPPViewModelTestInCS bin Debug Debug WPFViewModelInCPP 银行 CPPViewModel CPPViewModelTestInCS 箱子 调试 调试 令我惊讶的是,更高级别的调试似乎是C和C++/CLI项目使用的公共文件夹

WPFViewModelInCPP\Debug包含BackingStore.dll、CPPDemoViewModel.dll、CPPViewModelTest.dll及其关联的.ilk和.pdb文件

WPFViewModelInCPP\CPPViewModelTestInCS\bin\Debug包含CPPDemoViewModel和CPPViewModelTestInCS.dll和.pdb文件,但不包含备份存储。但是,手动将BackingStore复制到该目录中并没有修复错误。

CPPDemoViewModel具有属性Copy Local set,我假设该属性在引用if时负责复制其DLL。我无法将C#项目中的引用添加到纯C DLL中——它只是说无法添加对备份存储的引用

我不确定我是否只有一两个问题

我可以使用老式的复制构建步骤将BackingStore.dll复制到任何给定的C#project目录中,尽管我希望新的.net模型不需要这样做

DependencyWalker告诉我缺少的文件是GPSVC.dll,这表明存在安全设置问题。我怀疑这是在转移注意力

edit2
如果将BackingStore.dll的手动副本与可执行文件相邻,GUI现在可以正常工作。C++测试项目仍然存在一些问题,我怀疑是因为测试项目的运行环境,但现在我可以没有它。

是C和C++的DLL和正在执行的C组件中的目录相同吗? 您可能必须更改项目输出设置,以便C#程序集和其他DLL最终都位于同一文件夹中

我经常在这样的情况下使用;这是一个健全的检查,显示所有的依赖关系实际上都可以找到


应用程序运行后,您可能还想试用正在运行的代码,以查看引用了哪些DLL以及它们的位置。

这是一个有趣的难题。我以前从未听说过在从C#调用C++/CLI后从C++/CLI加载本机.dll时出现问题。我只能假设问题正如建议的那样,并且您的.DLL根本不在程序集加载程序可以找到的路径中


如果Daniel的建议不起作用,我建议您尝试将本机C代码静态链接到C++/CLI程序(如果可以的话)。这肯定会解决问题,因为.DLL将被完全吸收到C++/CLI.DLL中

确保目标系统具有正确的MS Visual C运行时,并且您没有意外地使用调试运行时构建C dll。

GUI的答案是添加预构建步骤,而不是更改输出设置

copy $(ProjectDir)..\Debug\BackingStore.* $(TargetDir)
测试项目的答案是将缺少的DLL添加到testrunconfig的Deployment选项卡。您可以通过直接编辑默认的LocalTestRun.testrunconfig(显示在解决方案中的“解决方案项”下)或右键单击解决方案并添加新的测试运行配置来执行此操作,该配置随后将显示在主测试菜单下


感谢您对测试配置的回答,让我找到了答案。

发生这种情况的原因是,在CRT有机会初始化之前,您正在从托管代码加载DLLMAIN。您可能没有任何托管代码,可以直接执行或直接执行,而不受DllMain通知的影响。(参见:Visual C++程序员的专家C++ + CLI:.NET,第11章++)。 或者您没有定义任何本机入口点,但您已链接到MSVCRT。CLR是使用/CLR自动初始化的,这个细节会引起很多混乱,必须加以考虑。混合模式DLL实际上通过使用热修补类中所有托管入口点vtable来延迟加载CLR

围绕这个主题的许多类初始化问题,有时加载程序锁定和延迟加载CLR有点棘手。尝试声明全局的静态,不要使用#pragma managed/unmanaged,每个文件用/clr隔离代码

如果您无法将代码从托管代码中隔离出来,并且遇到了问题,(在采取了其中一些步骤之后),您还可以考虑自己托管CLR,或者创建一个域管理器,这将确保运行时事件和引导完全“在环中”

T