C#到C ++ / CLI到C DLL System.IO.FileNotFoundException
我收到System.IO.FileNotFoundException: The specified module could not be found
运行调用C ++ / CLI程序集的C#代码时System.IO.FileNotFoundException: The specified module could not be found
,C ++ / CLI程序集又调用纯C DLL。 只要实例化一个调用纯C DLL函数的对象就会发生这种情况。
BackingStore是纯C.CPPDemoViewModel是C ++ / CLI调用BackingStore它有一个对BackingStore的引用。
我尝试了最简单的案例 – 添加一个新的C#unit testing项目,它只是试图创建一个在CPPDemoViewModel中定义的对象。 我从C#项目添加了一个引用到CPPDemoViewModel。
只需添加对CPPDemoViewModel的引用,C ++ / CLI测试项目就可以正常工作,因此它可以在语言之间进行。
我正在使用Visual Studio 2008 SP1和.Net 3.5 SP1。 我正在构建Vista x64,但一直小心确保我的平台目标设置为x86。
这感觉就像一些愚蠢和明显的我想念但是浪费时间试图私下解决它会更加愚蠢,所以我在这里让自己尴尬!
这是对一个移植大量遗留C代码的项目的测试,我将其保存在一个带有在C ++ / CLI中实现的ViewModel的DLL中。
编辑检查目录后,我可以确认尚未复制BackingStore.dll。
我有一个标准的独特项目文件夹,使用典型的多项目解决方案创建。
WPFViewModelInCPP 备份存储 CPPViewModel CPPViewModelTestInCS 箱子 调试 调试
令我惊讶的是,更高级别的Debug似乎是C和C ++ / CLI项目使用的公共文件夹。
WPFViewModelInCPP \ Debug包含BackingStore.dll,CPPDemoViewModel.dll,CPPViewModelTest.dll及其关联的.ilk和.pdb文件
WPFViewModelInCPP \ CPPViewModelTestInCS \ bin \ Debug包含CPPDemoViewModel和CPPViewModelTestInCS .dll和.pdb文件,但不包含BackingStore。 但是,手动将BackingStore复制到该目录并不能解决该错误。
CPPDemoViewModel具有属性Copy Local set,我假设它负责在引用if时复制其DLL。 我无法将C#项目的引用添加到纯C DLL中 – 它只是说无法添加对引用存储的引用。
我不确定我是否只有一两个问题。
我可以使用老式的复制构建步骤将BackingStore.dll复制到任何给定的C#项目目录中,尽管我希望新的.net模型不需要这样做。
DependencyWalker告诉我丢失的文件是GPSVC.dll, 已建议表明安全设置问题。 我怀疑这是一只红鲱鱼。
edit2将BackingStore.dll的手动副本与可执行文件相邻,GUI现在可以正常工作。 C#测试项目仍有问题,我怀疑是由于测试项目的运行时环境,但我现在可以没有这个。
C和C ++ DLL是否与正在执行的C#程序集位于同一目录中?
您可能必须更改项目输出设置,以便C#程序集和其他DLL都在同一文件夹中。
在这样的情况下,我经常使用Dependency Walker ; 这是一个完整性检查,显示实际上可以找到所有依赖项。
应用程序运行后,您可能还想在正在运行的代码上试用Process Monitor ,以查看正在引用的DLL以及它们的位置。
除了更改输出设置之外,GUI的答案是添加了预构建步骤
copy $(ProjectDir)..\Debug\BackingStore.* $(TargetDir)
Test项目的答案是将缺少的DLL添加到testrunconfig的Deployment选项卡中。 您可以通过直接编辑默认的LocalTestRun.testrunconfig (显示在解决方案项下的解决方案中)或右键单击解决方案并添加新的测试运行配置来执行此操作,然后将显示在主测试菜单下。
感谢关于测试配置的SO问题的答案,以便我找到答案。
发生这种情况的原因是因为您要么在CRT有机会初始化之前从托管代码加载DLLMAIN。 您可能没有任何托管代码,可以直接或间接执行DllMain通知的效果。 (参见:Expert C ++ / CLI:.Net for Visual C ++ Programmers,chapter 11 ++)。
或者您没有定义本地入口点,但您已链接到MSVCRT。 使用/ clr为您自动初始化CLR,此详细信息会引起很多混淆,必须予以考虑。 混合模式DLL实际上通过使用热修补类中的所有托管入口点vtable来加载 CLR。
围绕这个主题的许多类初始化问题,加载器锁定和延迟加载CLR有时候有点小。 尝试声明全局静态,不要使用#pragma managed / unmanaged,用/ clr per-file隔离你的代码。
如果您无法将代码与托管代码隔离,并且遇到问题(在执行其中一些步骤之后),您还可以考虑自己托管CLR并且可能会尝试创建域管理器,这样可以确保完全“在循环中”运行时事件和引导。
这正是原因,它与您的搜索路径或初始化没有关系。 不幸的是,Fusion日志查看器没有那么多帮助(这是寻找.NET CLR程序集绑定问题而不是依赖walker的常用位置)。
静态链接也没有任何结果。 您不能静态链接混合模式的C ++ / CLI应用程序。
- 将DLLMAIN函数单独放入文件中。
- 确保此文件没有在构建选项中设置/ CLR ( 文件构建选项)
- 确保与/ MD或/ MDd链接,以及您链接的所有依赖项使用完全相同的CRT。
- 评估/ DEFAULTLIB和/ INCLUDE的链接器设置以识别任何可能的参考问题,您可以在代码中声明原型并使用/ INCLUDE覆盖默认的库链接解析。
祝你好运,也检查一下这本书非常好。
这是一个有趣的困境。 我从来没有听说过从C#调用C ++ / CLI后从C ++ / CLI加载本机.DLL的问题。 我只能假设问题是@Daniel L建议的那样,并且你的.DLL根本不在程序集加载器可以找到的路径中。
如果Daniel的建议没有成功,我建议您尝试将本机C代码静态链接到C ++ / CLI程序,如果可以的话。 这肯定会解决问题,因为.DLL将被完全吸收到C ++ / CLI .DLL中。
确保目标系统具有正确的MS Visual C运行时,并且您不会意外地使用调试运行时构建C dll。
有同样的问题切换到64位Vista。 我们的应用程序调用Win32 DLLs,这使得应用程序的目标构建混乱。 要解决它,我们做了以下事情:
- 转到项目属性;
- 选择Build选项卡;
- 将’Platform target:’选项更改为x86;
- 重建应用程序。
当我重新运行应用程序时,它工作。