在C++/CLI项目中识别有问题的依赖关系

10

我的应用程序编译得很好,但是我遇到了以下运行时错误:

System.IO.FileNotFoundException was unhandled
  HResult=-2147024770
  Message=Could not load file or assembly {Wrapper} or one of its dependencies. The specified module could not be found.

在调用应用程序中对 Wrapper 的引用看起来是正确的。Wrapper dll 存在于正确的位置。

这个项目曾经能够在别人的系统上构建和运行,我看过几次演示。那个人/电脑现在已不可用。自上次成功构建和运行以来,一些依赖项的路径发生了变化,我已经修复了所有与此相关的编译错误。

只想澄清一下我的项目结构:

Graph

Digraph G
{
    App [ label = "My C# Application"]
    Wrapper [ label = "C++/CLI Wrapper"]
    Lib [ label = "C++ Library"]
    Dll [ label = "My helper C# DLL"]
    CDep [ label = "Series of deep C++ dependencies managed \n by CMake for Lib, hard coded relative paths for Wrapper."]
    App->Wrapper->Lib->CDep;
    App->Dll->Wrapper->CDep;
}

Wrapper是一个C++库的C++/CLI封装。 当我们试图在应用程序中加载具有对Wrapper的using语句的类时,就会触发此错误。

Wrapper确实有很多依赖项,但错误消息并没有指出哪个依赖项存在问题。 这是一个庞大而复杂的系统,其中大部分由其他团队构建。 C++组件使用CMake获取所有正确的依赖项,但CMake不支持C#原生。

我尝试使用fuslogvw查找绑定错误,但除非我改变设置以包括所有绑定,否则它什么也没显示给我,然后它只显示成功绑定。 http://msdn.microsoft.com/en-us/library/e74a18c4(v=vs.100).aspx

路径很长,但不超过256个字符。

我的Dll编译收到了警告(请参见上面的图表): Warning 1 在被构建的项目“MSIL”和引用“{cli_wrapper.dll}”之间存在处理器体系结构不匹配,“AMD64”。 此不匹配可能导致运行时故障。 请考虑通过配置管理器更改项目的目标处理器体系结构,以使项目和引用之间的处理器体系结构对齐,或者依赖于具有与项目的目标处理器体系结构匹配的处理器架构的引用。

在配置管理器中,Dll正在构建“Any CPU”平台,而Wrapper正在构建为“x64”。 我已将dll更改为x64。 我仍然遇到了运行时错误。

无法加载文件或程序集或其某个依赖项进行了清理,删除了构建目录内容。 没有变化。 重新打开Visual Studio。 没有变化。 尝试更改程序集名称、默认命名空间和项目名称以匹配。 没有变化。

无法加载文件或程序集'xxx'或其某个依赖项。 尝试使用不正确的格式加载程序 我认为我们必须编译为64位。 我们依赖于一个64位的C++库。

无法加载文件或程序集 ... 参数不正确 我是本地管理员。

如何在.NET中启用程序集绑定失败日志记录(Fusion) 尝试了注册表设置,但它们似乎只是fuslogvw设置。 可用的日志数据没有改善。

许多其他类似的问题都有针对ASP或服务安装的具体答案。


3
+1. 提醒一下。任何暗示“你尝试了什么?”的建议都应该被用铁管打击。我不是 CLI/.NET 领域的专家,所以对此没有答案,但我真诚地希望你能找到一个答案。你值得拥有答案,即使仅仅因为这个问题的提出方式很出色 - WhozCraig
如果我能列出所有的依赖项,我该如何验证它们是否都已经编译为64位?仅仅因为我从64位发布文件夹中获取它们,并不意味着它们是正确的。 - Denise Skidmore
1
好问题!首先,如果您的非托管库是为x64环境构建的,则所有托管组件都需要构建为x64,而不是AnyCPU。但是,如果存在CPU架构不匹配,则会遇到“BadImageException”错误。我的问题是:运行时错误确切发生在什么时候?您的应用程序第一次调用包装器时?还是更早/更晚?此外,您可以尝试将包装器库加载到[Dependency Walker](http://www.dependencywalker.com/)中。它已经帮助了我很多! - Carsten
重要提示。开启融合日志记录后,它会显著地减慢 Visual Studio 的运行速度。在诊断问题后请禁用它。 - Denise Skidmore
我也遇到了这个问题。我发现需要将这些本地C++ dlls的目录添加到PATH中。你可以在这里找到更多信息:http://blogs.msdn.com/b/jorman/archive/2007/08/31/loading-c-assemblies-in-asp-net.aspx - Bargitta
显示剩余12条评论
3个回答

6

我找到了问题所在。有一些库的版本都可以使用,我使用了其中一个版本的包含文件和另一个版本的已编译库。使用Dependancy Walker可以找出哪个库出了问题,如果Aschratt将此作为答案发布而不是评论,我就会接受他的回答。


3
本周早些时候,我在类似的项目中遇到了同样的错误。首先,在使用C++/CLI时,“Any CPU”不存在。我必须为x86构建才能完成任务。
此外,尽管我的包装器的依赖关系得到了满足,但是CLR捕获的是包装器的异常,因此它声称包装器缺少依赖项。实际上,我缺少了C++ DLL的依赖项,我的包装器包装了它(在我的情况下,只是忘记将SDL2.dll和OpenAL32.dll放入我的新“Release”配置输出文件夹中...我之前只使用了Debug配置,其中我已经放置了这些DLL)。
如果您确定已经解决了包装器的依赖关系,我建议使用Dependency Walker检查本地DLL的依赖关系。您还可以使用Assembly.GetReferencedAssemblies与外部脚本/程序一起使用,以再次检查您的包装器(或者使用ILSpy:http://ilspy.net/)。
最后,请查看这个:http://www.codeproject.com/Articles/442784/Best-gotchas-of-Cplusplus-CLI。他详细介绍了我提出的前两个建议以及其他一些建议。
祝你好运!

0
我最近遇到的一个备选根本原因是,我正在处理的应用程序使用模拟身份,并且被模拟的用户没有访问GAC或某些dll所在文件夹的权限。您需要为该用户授予权限,或更改模拟身份的方式,在模拟开始之前加载依赖项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接