我越来越 System.IO.FileNotFoundException: The specified module could not be found 当运行调用 C++/CLI 程序集的 C# 代码时,该程序集又调用纯 C DLL。一旦调用纯 C DLL 函数的对象被实例化,就会发生这种情况。

BackingStore 是纯 C 语言。CPPDemoViewModel 是调用 BackingStore 的 C++/CLI,它具有对 BackingStore 的引用。

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

C++/CLI 测试项目只需添加对 CPPDemoViewModel 的引用即可正常工作,因此需要在两种语言之间进行切换。

我使用 Visual Studio 2008 SP1 和 .Net 3.5 SP1。我正在 Vista x64 上构建,但一直小心确保我的平台目标设置为 x86。

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

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

编辑检查目录后,我可以确认 BackingStore.dll 尚未被复制。

我有使用典型的多项目解决方案创建的标准唯一项目文件夹。

WPFViewModelInCPP
  BackingStore
  CPPViewModel
  CPPViewModelTestInCS
    bin
      Debug
  Debug

令我惊讶的是,更高级别的 Debug 似乎是 C 和 C++/CLI 项目使用的通用文件夹。

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

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

CPPDemoViewModel 具有属性 复制本地 我假设它负责在引用 if 时复制其 DLL。我无法将 C# 项目的引用添加到纯 C DLL - 它只是说 无法添加对后备存储的引用。

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

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

DependencyWalker 告诉我丢失的文件是 GPSVC.dll 已建议 表示安全设置问题。我怀疑这是一条红鲱鱼。

编辑2通过将 BackingStore.dll 的手动副本与可执行文件相邻,GUI 现在可以正常工作。C# 测试项目仍然存在问题,我怀疑这些问题是由于测试项目的运行时环境造成的,但我现在可以没有这个问题。

有帮助吗?

解决方案 2

GUI 的答案除了更改输出设置之外,还添加了预构建步骤

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

测试项目的答案是将缺少的 DLL 添加到 testrunco​​nfig 的“部署”选项卡中。您可以通过直接编辑默认值来实现 LocalTestRun.testrunco​​nfig (出现在解决方案中的解决方案项下)或右键单击解决方案并添加新的测试运行配置,该配置随后将出现在主测试菜单下。

感谢您的回答 这个问题 测试配置引导我找到答案。

其他提示

是在相同的目录中对正在执行C#组件中的C和C ++的DLL?

您可能有这样的C#组件与其他DLL都在同一个文件夹中最终改变你的项目输出设置。

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

在您的应用程序正在运行,你也想尝试进程监视器上所运行的代码,以查看正在被引用的DLL和它们所在的位置。

发生这种情况的原因是您在 CRT 有机会初始化之前从托管代码加载 DLLMAIN。你可能没有任何托管代码,被执行 直接地 或者 间接地 受 DllMain 通知的影响。(看:专家 C++/CLI:面向 Visual C++ 程序员的 .Net,第 11 章 ++)。

或者您没有定义任何本机入口点,但您已链接到 MSVCRT。CLR 会使用 /clr 自动为您初始化,这个细节会造成很多混乱,必须予以考虑。实际上是一个混合模式的DLL 延迟负载 通过使用热修补类中的所有托管入口点 vtable 来更新 CLR。

许多类初始化问题都围绕着这个主题,加载器锁和延迟加载 CLR 有时有点棘手。尝试声明全局静态并且不要使用#pragma托管/非托管,使用/clr每个文件隔离您的代码。

如果您无法将代码与托管代码隔离,并且遇到麻烦(在采取其中一些步骤之后),您还可以考虑自己托管 CLR,并且可能需要创建一个域管理器,这将确保您完全处于运行时事件和引导的“循环内”。

这就是为什么,它与您的搜索路径或初始化无关。不幸的是,Fusion 日志查看器并没有多大帮助(这是查找 .NET CLR 程序集绑定问题而不是依赖项遍历器的通常位置)。

静态链接也与此无关。你可以 不是 静态链接混合模式的 C++/CLI 应用程序。

  1. 将 DLLMAIN 函数单独放入一个文件中。
  2. 确保该文件确实 不是/CLR 在构建选项中设置(文件 构建选项)
  3. 确保您与 /MD 或 /MDd 的链接,以及您链接的所有依赖项都使用完全相同的 CRT。
  4. 评估链接器的 /DEFAULTLIB 和 /INCLUDE 设置以识别任何可能的引用问题,您可以在代码中声明原型并使用 /INCLUDE 覆盖默认库链接解析。

祝你好运,也检查一下那本书,非常好。

这是一个有趣的两难境地。我从来没有听说过,从C#之前打电话进去之后,从C ++ / CLI加载本地.DLL文件的问题。我只能假设问题是 @Daniel大号建议,并且您的.DLL根本不是在组装装载机可以找到一个路径。

如果丹尼尔的建议不工作了,我建议你尝试静态本地C代码链接到C ++ / CLI程序,如果你能。这当然可以解决这个问题,作为.DLL随后将被完全吸收到C ++ / CLI .DLL。

确认目标系统有正确的微软的Visual C运行时,那你是不是偶然建设有一个调试运行时的C DLL。

切换到 64 位 Vista 时遇到同样的问题。我们的应用程序正在调用 Win32 DLL,这混淆了应用程序的目标构建。为了解决这个问题,我们执行了以下操作:

  1. 转到项目属性;
  2. 选择“构建”选项卡;
  3. 将“平台目标:”选项更改为 x86;
  4. 重建应用程序。

当我重新运行该应用程序时,它起作用了。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top