【问题标题】:Why do I get assembly bind failure in IIS CGI program为什么在 IIS CGI 程序中出现程序集绑定失败
【发布时间】:2010-02-19 03:18:31
【问题描述】:

我有一个 C# 程序在 XP Pro SP3 上的 IIS 中作为 CGI 应用程序运行。在我引用库程序集类并在程序代码中使用它之前,它运行良好。如果我手动运行 CGI 程序,它会加载并执行。但是,当它由 IIS 运行时,尽管引用的程序集与父可执行文件位于同一目录中,但它无法绑定。这是我得到的绑定日志:

=== 预绑定状态信息 ===
日志:用户 = STEVIENEW\IUSR_STEVIENEW
日志:DisplayName = VOEvent,版本=3.0.7.0,文化=中性,PublicKeyToken=null
 (完全指定)
日志:Appbase = file://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/
日志:初始 PrivatePath = NULL
调用程序集:MsgChkCGI,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null。
===
LOG:此绑定在默认加载上下文中开始。
LOG:未找到应用程序配置文件。
LOG:使用来自 c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config 的机器配置文件。
LOG:此时未将策略应用于引用(私有、自定义、部分或基于位置的程序集绑定)。
日志:正在尝试下载新的 URL 文件://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent.DLL。
日志:正在尝试下载新的 URL 文件://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent/VOEvent.DLL。
日志:正在尝试下载新的 URL 文件://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent.EXE。
日志:正在尝试下载新 URL file://?/C:/Documents and Settings/Robert B. Denny/My Documents/iis/vomsgtst/VOEvent/VOEvent.EXE。

Appbase 是正确的(尽管 URI 中的 '?' 是什么????也许这是一个提示)。程序集 voevent.dll 绝对与 MsgChkCGI.exe 位于同一目录(Appbase!)中。如果我只是双击 exe,它会正确启动(并且由于缺少 CGI 环境变量而出现错误,但这是意料之中的)。

有人知道怎么回事吗?

【问题讨论】:

  • 很奇怪,fusion binder连我放的MsgChkCGI.exe.config文件都找不到!我尝试使用程序集的确切路径/版本向其中添加 assemblyBIding 信息。它甚至找不到@#$%^ app.config 文件!怎么了?
  • 路径中的那个问号是红旗。
  • 数据点:我在我古老的 O'Reilly WebSite Pro 服务器上尝试了这个 CGI,也在 XP Pro 上,它运行良好!!!所以这是一个特定于 IIS 的问题,它处理在 .NET CLR 下运行的 CGI 程序。我需要解决它,因为这个 CGI 需要在我的 IIS 系统上运行。

标签: c# .net iis cgi assembly-resolution


【解决方案1】:

我不确定为什么会发生这种情况。

作为一种解决方法,您可以处理 AppDomain.CurrentDomain.AssemblyResolve

编辑:请注意,如果您在添加处理程序的同一方法中使用来自另一个程序集的类型,则不会触发该事件,因为该程序集将在代码之前由 JITter 加载该方法实际上已被执行。
因此,您需要将任何使用来自其他程序集的类型的代码放在一个单独的方法中,然后在处理完AssemblyResolve 之后调用该方法。

2nd编辑:致电Assembly.Load(File.ReadAllBytes(path))
另外,您能否编辑您的问题以包含来自Assembly.LoadFileFileNotFoundException 的所有详细信息?

【讨论】:

  • 似乎从未触发过此事件。问题似乎发生在程序开始执行之前,而不是在它第一次尝试在该引用程序集中创建类型时。感谢您的尝试!
  • 添加处理程序,然后将所有代码放在一个单独的函数中,并在处理程序之后调用它。它工作。
  • 谢谢,我试试看。感谢您的坚持 :-) 呃,我假设您的意思是在 Main() 中将处理程序添加到事件中,然后在此之后调用一个包含整个程序其余部分的函数。
  • 它被击中了。现在来看令人惊奇的部分:我使用 ResolveEventArgs 来识别它试图解析的程序集(它是完全限定的程序集名称)并构造程序集文件的路径。然后我在该路径上调用 File.Exists(),它返回 true。然后,我在调用 Assembly.LoadFile() 时使用完全相同的路径(字符串变量),它会引发 System.IO.FileNotFoundException!见上文,它在非 IIS 网络服务器上的 Windows 上运行,无需跳过这些环节。这是 IIS 正在做的事情!
  • @bob:是的,.net 有一个非常“有趣”的 FNF 异常用法。这也可能意味着找不到依赖项之一。启用 Fusion 日志以获取详细信息。
【解决方案2】:

根据 SLaks 的回答,我已经编写了解决方案

Assembly assembly = Assembly.GetEntryAssembly();
Uri codeBaseUrl = new Uri(assembly.CodeBase);
// hack IIS CGI malformed url
if (codeBaseUrl.ToString().StartsWith("file:///?/"))
    codeBaseUrl = new Uri("file:///" + codeBaseUrl.ToString().Substring(10));
string dir = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
dir = Path.GetDirectoryName(dir);

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    var dllName = new AssemblyName(args.Name).Name + ".dll";
    dllName = Path.Combine(dir, dllName);

    return Assembly.LoadFile(dllName);
};

但是.NET的其他部分由于格式错误的URLfile:///?/而失败,所以我想知道解决方案如何强制不更改URL。通过正常的URL

【讨论】:

    【解决方案3】:

    另一种解决方案是使用来自另一个 CGI 的 EXE 启动进程,例如来自 PHP、其他 EXE 或 CMD。

    要将 *.cmd 用作 CGI,请键入运行 EXE 的简单 CMD 脚本

    @echo off
    %~dp0\myprogram.exe
    

    并配置 IIS 以将 CMD 作为 CGI 运行。对 EXE 文件执行相同的操作,只需在正确的设置中键入您的 CMD。然后转到 Handler Mappings,选择 CGI-exe 并将*.exe 更改为*.cmd。最后转到 CGI 面板并将 Use new console... 更改为 True

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 2015-11-14
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      相关资源
      最近更新 更多