IIS加载哪些ASP.NET Web应用程序的DLL文件?

时间:2015-10-16 10:03:07

标签: asp.net .net iis

我找不到任何有关它的信息。有没有人知道IIS是加载Web应用程序的bin目录中的所有dll还是任何目录中的所有dll,或者只是项目引用的目录(在这种情况下它是如何确定哪个dll是“master”)?

我刚刚遇到有人在部署新版本之前没有从Web应用程序目录中删除所有文件的情况,而某些dll已重命名。这个冗余的dll位于MVC 4 Web应用程序的bin目录中。

4 个答案:

答案 0 :(得分:7)

它不会自动加载任何DLL。

它加载的每个DLL都与请求直接相关。首先,编译Global.asax(可以从bin加载一些DLL)。然后,在web.config中定义了任何HTTP模块和HTTP处理程序(与上一步有一些重叠)。然后是最终的aspx / asmx / ...其他一些可能会作为配置的一部分或类似的东西,但所有加载的DLL总是显式加载。

因此,没有“主”DLL。 web.config,Global.asax和实际请求的文件是决定实际发生的事情的文件。如果你需要加载一个特定的DLL(并且你不是简单地引用它),你需要自己动手。

修改

由于这有点复杂,让我展开一下。

这里要记住的主要事情是ASP.NET 总是动态编译 - 至少在一定程度上。至少,你总是必须编译Global.asax - 没有办法解决它。现在,ASP.NET中的动态编译有一个重要的特性 - 它是进程外的(至少对于遗留的编译器 - 我不确定Roslyn +)。因此,无论编译器如何查找引用等,都不会实际反映加载到工作进程本身的内容 - 特别是应用程序域。

动态编译由.NET端的BuildManager类处理 - http://referencesource.microsoft.com/#System.Web/Compilation/BuildManager.cs,fb803c621f3806a8。由于您询问了“主DLL”,因此最相关的位将是处理Global.asax编译的代码,这是任何ASP.NET应用程序的起点之一。最初的编译由EnsureTopLevelFilesCompiled方法处理。查看代码,您可以轻松查看第一步:

CompileResourcesDirectory();
CompileWebRefDirectory();
CompileCodeDirectories();

...

CompileGlobalAsax();

对于网站与网络项目以及预编译网站,大多数情况略有不同,但我们几乎可以忽略这一点。现在,代码并不是世界上最简单的代码,但基本上,它归结为生成一堆程序集 - 每个代码目录大约有一个程序集。同样,这是在进程外完成的 - 虽然编译器必须在bin中加载二进制文件,但它们不一定会加载到ASP.NET工作进程中。相反,实际上只加载了必要的引用。

最重要的是动态编译确实会做很多解决方案来帮助你(毕竟,你甚至不知道编译类型的动态程序集的名称,所以你可以不指定它!) - 但这并不意味着bin中的所有程序集都加载到ASP.NET应用程序域中。检查此问题的最简单方法是添加一个未在bin的任何位置引用的空程序集,然后打印出AppDomain.Current.GetAssemblies - 您将看到在编译过程中确实触摸了文件时, 加载到 ASP.NET应用程序域中。如果您尝试在ASP.NET中实现某些动态模块加载,则需要牢记这一点 - 您需要自己加载这些程序集。

您可以调整编译在web.config中的工作方式(尤其是全局编译) - 例如,默认情况下,bin中的所有程序集都会被加载以用于编译目的,但您可以使用{ {1}}标记樱桃选择你想要的任何东西。

答案 1 :(得分:7)

作为一项实验,我制作了一个新的ASP.NET Webforms项目,并将其部署到IIS。然后,我创建了第二个.net类库,并将.dll文件复制到Web应用程序的\bin文件夹(类库未在ASP.NET应用程序的任何位置引用或使用)。

我启动了SysInternals ProcMon,在IIS中回收了应用程序池和网站,并在浏览器中请求了该网站。

w3wp.exe确实在首页请求中读取了类库.dll文件。

This MSDN page还声明:

  

您可以将已编译的程序集存储在Bin文件夹中,Web应用程序中任何位置的其他代码(例如页面代码)都会自动引用它。一个典型的例子是你有一个自定义类的编译代码。您可以将已编译的程序集复制到Web应用程序的Bin文件夹中,然后该类可用于所有页面。

     

Bin文件夹中的程序集不需要安装在全局程序集缓存(GAC)中。在Bin文件夹中存在.dll文件足以让ASP.NET识别它。

这似乎暗示ASP.NET会反映它在\bin中找到的程序集并自动加载它们。

有趣的是,即使您将非.NET文件(我从C:\ Windows复制twain.dll)放入ASP.NET bin文件夹,也会读取这些文件。运行时似乎只是询问文件系统\bin\*并遍历文件以检查要加载的.NET程序集。

我还注意到,如果您将其添加到web.config文件中:

  <system.web>
    <compilation targetFramework="4.5">
      <assemblies>
        <clear />
      </assemblies>
    </compilation>

然后页面将不再运行,错误

  

无法加载“WebApplication1.Global”类型。

因此,似乎运行时不再从程序集中加载这些类。 然而,运行时仍会从驱动器中读取未引用的控制台应用程序.dll和non.net程序集twain.dll。

所以,答案归结为“加载所有dll”的意思......如果你的意思是在运行时可用,那么如果你指定自己的{{1},那么答案就是“不”。但默认是加载所有。但如果你的意思是什么文件是物理阅读,那么“是”。

答案 2 :(得分:0)

  

是的,asp.net会加载bin目录中的所有dll。

我最近写了一篇关于这个问题的博客,因为我遇到了一个没有在我的项目中使用的dll的问题。请参考this博客,尝试讨论其他几种常见情况。

答案 3 :(得分:-2)

Asp.net将所有dll加载到bin目录中。