具有非托管依赖项的 64 位托管程序集未在 IIS/ASP.NET MVC 4 中加载

具有非托管依赖项的 64 位托管程序集未在 IIS/ASP.NET MVC 4 中加载

问题描述:

我有一个几乎空的 ASP.NET MVC4 项目,它引用了一个 64 位托管程序集,该程序集具有一组非托管依赖项.

I have an almost empty ASP.NET MVC4 project referencing a 64 bit managed assembly, which has a set of unmanaged dependencies.

通过引用以正常方式引用托管程序集.

The managed assembly is referenced the normal way through references.

非托管依赖项在构建后事件中复制到 bin 文件夹 - 并在 Web 应用程序启动时出现(这已经过验证).

The unmanaged dependencies are copied to the bin folder on a post build event - and are present when the web app is started (this has been verified).

问题是我得到:

无法加载文件或程序集msvcm80.DLL"或其依赖项之一.动态链接库 (DLL) 初始化例程失败.(来自 HRESULT 的异常:0x8007045A)

Could not load file or assembly 'msvcm80.DLL' or one of its dependencies. A dynamic link library (DLL) initialisation routine failed. (Exception from HRESULT: 0x8007045A)

这是非托管依赖项之一.完整列表是:

This is one of the unmanaged dependencies. The full list is:

  • iconv.dll
  • lbm.dll
  • libeay32.dll
  • msvcm80.dll
  • msvcp80.dll
  • msvcr80.dll

托管 dll 是针对 x64 构建的,所有依赖项也是 x64(通过使用 Dependency Walker 验证).

The managed dll is built against x64 and all the dependencies are also x64 (verified by using Dependency Walker).

现在我还创建了一个空白的控制台应用程序、一个 windows 窗体应用程序和一个自托管的 Web Api,其中包含相同的代码(用于使用托管程序集启动实例)并且它们都可以正常工作(强制构建时)目标为 x64).

Now I have also created a blank console app, a windows form app and a self-hosted Web Api which contains the the same code (for firing up instances using the managed assembly) and they all work fine (when forcing the build target to be x64).

使用Fusion Log(先清空,然后加载web app,刷新日志查看器),可以看到加载有问题:

Using Fusion Log (clearing it first, then loading the web app and refreshing the log viewer), I can see that there are problems loading:

  • iconv.dll
  • libeay32.dll
  • lbm.dll

它们都有相似的日志文件:

All of them have similar log files:

LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/root/3b2d5b3e/b1b5f1f5/iconv.DLL.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/root/3b2d5b3e/b1b5f1f5/iconv/iconv.DLL.
LOG: Attempting download of new URL file:///C:/.../bin/iconv.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:...iniconv.dll
LOG: Entering download cache setup phase.
ERR: Error extracting manifest import from file (hr = 0x80131018).
ERR: Setup failed with hr = 0x80131018.
ERR: Failed to complete setup of assembly (hr = 0x80131018). Probing terminated.

所以它实际上确定依赖项在本地bin文件夹中,但由于某种原因无法使用它们.

So it actually figures out that the dependencies are in the local bin folder, but it cannot use them for some reason.

从文件中提取清单导入时出错 (hr = 0x80131018)"是什么错误?是什么意思?

What does the error "Error extracting manifest import from file (hr = 0x80131018)." mean?

依赖项不在 GAC 中,也没有使用 regsvr32(不是 COM)注册.

The dependencies are not in GAC and they are not registered using regsvr32 (not COM).

令我困惑的是,它在 IIS 之外运行良好(我什至尝试将应用程序池上的凭据设置为与本地网络凭据相同 - 当然,这并没有什么区别).

What puzzles me is that is works fine outside IIS (I even tried to set up the credentials on the app pool to be the same as the local network credentials - which did not make a difference, of course).

关于如何调试这个问题有什么好的想法吗?

编辑:我现在可以在本地开发人员机器上运行 ASP.NET 站点,但是当它部署到另一台服务器时不能.

EDIT: I am now able to run the ASP.NET site on my local developer machine, but not when it is deployed onto another server.

我本地机器的修复"是从 bin 目录中删除 msvcm80.dll(C 运行时).该程序集(可能)仍然需要,但在其他地方查找(大概是因为我在 WinSxS 中安装了正确"版本的 CRT(可分发)).

The "fix" for my local machine, was to remove the msvcm80.dll (C runtime) from the bin directory. The assembly is (probably) still needed, but is looked up somewhere else (presumably because I have the "correct" version of CRT (distributable) installed in WinSxS).

深入研究,我发现托管程序集据说依赖于 msvcm80.dll 版本 8.00.50727.6195 (x64),但该特定版本未安装在我的本地系统上(我只将它放在依赖文件夹中)-但我在 WinSxs 中有一个更新的 (8.00.50727.6910).

Digging into that, I see that the managed assembly is supposedly dependent on msvcm80.dll version 8.00.50727.6195 (x64), but that particular version is not installed on my local system (I only have it in a dependency folder) - but I do have a newer one in WinSxs (8.00.50727.6910).

那么IIS在不直接添加到bin文件夹中时会选择哪一个?

So which one is IIS picking up when not adding it directly in the bin folder?

第二次编辑:所以看起来 lbm.dll 直接依赖于 msvcr80.dll,但它也依赖于 iconv.dll,而 iconv.dll 又依赖于 msvcr80.dll.但是,根据 Dependency Walker (depends.exe),这两个依赖项不会从同一目录解析(即使它们具有相同的版本!).

2nd EDIT: So it looks like lbm.dll has a direct dependency to msvcr80.dll, but it also has a dependency to iconv.dll which again has a dependency to msvcr80.dll. However, according to Dependency Walker (depends.exe), those two dependencies are not resolved from the same directory (even when they have the same version!).

如果我确保间接依赖项在 PATH 环境变量中,而第二个依赖项在 WinSxS 中,则它可以工作.这显然不够好,但我无法弄清楚如何强制从单个位置/文件加载直接和间接依赖项.

If I make sure that the indirect dependency is in the PATH environment variable and the 2nd dependency is in WinSxS it works. This is obviously not good enough, but I cannot figure out how to enforce that the direct and indirect dependency is loaded from a single location/file.

使用像 Dependency Walker 这样的工具你会发现 lbm.dll 及其依赖项仅依赖于 msvcr80.dll 而不是 msvcp80.dllmsvcm80.dll 即使这两个文件包含在 lbm.dll 用来加载正确版本的 Visual C++ 2005 运行时库的 Microsoft.VC80.CRT.manifest 中.

Using a tool like Dependency Walker you will find that lbm.dll and its dependencies only depend on msvcr80.dll and not msvcp80.dll and msvcm80.dll even though these two files are included in the Microsoft.VC80.CRT.manifest used by lbm.dll to load the correct version of the Visual C++ 2005 runtime library.

从 bin 文件夹中删除 msvcp80.dllmsvcm80.dll 应该可以解决您的问题.

Removing msvcp80.dll and msvcm80.dll from you bin folder should fix your problem.