我有一个几乎空的 ASP.NET MVC4 项目,引用 64 位托管程序集,该程序集具有一组非托管依赖项。
通过引用以正常方式引用托管程序集。
非托管依赖项会在构建后事件中复制到 bin 文件夹,并在 Web 应用程序启动时出现(这已得到验证)。
问题是我得到:
无法加载文件或程序集“msvcm80.DLL”或其依赖项之一。动态链接库 (DLL) 初始化例程失败。 (HRESULT 异常:0x8007045A)
这是非托管依赖项之一。完整列表是:
- dll
- lbm.dll
- libeay32.dll
- msvcm80.dll
- msvcp80.dll
- msvcr80.dll
托管 dll 是针对 x64 构建的,所有依赖项也是 x64(通过使用 Dependency Walker 进行验证)。
现在我还创建了一个空白控制台应用程序、一个 Windows 窗体应用程序和一个自托管 Web Api,其中包含相同的代码(用于使用托管程序集启动实例),并且它们都工作正常(当强制构建目标为x64)。
使用 Fusion Log(首先清除它,然后加载 Web 应用程序并刷新日志查看器),我可以看到加载时出现问题:
它们都有相似的日志文件:
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:\...\bin\iconv.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 文件夹中,但由于某种原因无法使用它们。
错误“从文件中提取清单导入时出错 (hr = 0x80131018)”是什么意思?意思是?
依赖项不在 GAC 中,并且它们不是使用 regsvr32(不是 COM)注册的。
让我困惑的是,它在 IIS 之外工作得很好(我什至尝试将应用程序池上的凭据设置为与本地网络凭据相同 - 当然,这没有什么区别)。
关于如何调试这个问题有什么好主意吗?
EDIT:
我现在可以在本地开发人员计算机上运行 ASP.NET 站点,但是not当它部署到另一台服务器上时。
我的本地计算机的“修复”是从 bin 目录中删除 msvcm80.dll(C 运行时)。该程序集(可能)仍然需要,但在其他地方查找(大概是因为我在 WinSxS 中安装了“正确”版本的 CRT(可分发))。
深入研究后,我发现托管程序集据说依赖于 msvcm80.dll 版本 8.00.50727.6195 (x64),但该特定版本未安装在我的本地系统上(我只将它放在依赖项文件夹中) - 但我确实这样做WinSxs 中有一个较新的版本 (8.00.50727.6910)。
那么,如果不直接将其添加到 bin 文件夹中,IIS 会选择哪一个呢?
2nd EDIT:
因此,看起来 lbm.dll 直接依赖于 msvcr80.dll,但它也依赖于 iconv.dll,而 iconv.dll 又依赖于 msvcr80.dll。但是,根据 Dependency Walker (depends.exe),这两个依赖项不是从同一目录解析的(即使它们具有相同的版本!)。
如果我确保间接依赖项位于 PATH 环境变量中,而第二个依赖项位于 WinSxS 中,则它可以工作。这显然不够好,但我无法弄清楚如何强制从单个位置/文件加载直接和间接依赖项。