编译器失败,错误代码为-1073741502,仅适用于一页

时间:2016-12-23 20:28:52

标签: c# asp.net .net iis

我知道有很多关于编译器失败的讨论,错误代码为-1073741502 ,但我的情况完全不同。

对于我的ASP.NET网站,它是针对特定的.aspx页面(名称Report.aspx)生成此错误代码。

生成错误的步骤

  1. 加载Report.aspx(第一次可以正常工作)
  2. 对Report.aspx进行一些更改。 Html更改/ CSS更改
  3. 刷新Report.aspx并出现错误。
  4. 观察

    我注意到每次重建网站/解决方案/重新启动调试时,Report.aspx在首次加载时都能正常工作,当我在该页面进行一些更改时会出现问题(步骤2)。

    我尝试的事情

    任何新的产品?

1 个答案:

答案 0 :(得分:0)

- > https://blogs.msdn.microsoft.com/friis/2012/09/19/c-compiler-or-visual-basic-net-compilers-fail-with-error-code-1073741502-when-generating-assemblies-for-your-asp-net-site/

[2018年1月更新:]本文适用于分别运行IIS 7.5和8.5的Windows 2008R2服务器和Windows 2012R2服务器。如果您遇到下述症状,请直接进入本文末尾所述的解决方案更新。

几天前,我有一个支持电话,其中部署到Windows 2008 R2服务器并在IIS 7.5上运行的ASP.net应用程序不时崩溃。当应用程序中的页面崩溃时,返回500错误代码,并显示类似于以下内容的错误消息:

编译器错误消息:编译器失败,错误代码为-1073741502。

然后出现错误,然后是启动.Net编译器的命令行。这可能是一个非常令人生畏的错误,因为它可以随机出现和消失,并且回收应用程序池或重新启动IIS将无济于事。如果您只需要解决错误,请直接转到文章的解决方案部分,如果没有,请继续阅读详细说明。

实际上是怎么回事:

ASP.net应用程序可以以多种模式部署到IIS服务器(我将在以下视频中详细讨论:http://linqto.me/IISArchP3),但基本上是ASP.net应用程序中的每个源代码文件(是它是一个.cs - C#文件或.vb - VB.Net文件)必须先编译才能在服务器上执行。通常,当来自最终用户的特定标准或资源的请求进入时,会发生这种情况。

假设我们有一个名为Default.aspx的应用程序。后面的页面代码用C#编写,存在于一个名为Default.aspx.cs的文件中。当第一个请求来自第一个访问该站点的用户时,.Net Runtime将注意到该页面尚未编译并将请求编译该页面 - 将C#代码转换为.dll可以执行 - 。

当必须编译页面时,将发生的事情是托管ASP.net应用程序的w3pw.exe(工作进程)将请求激活.Net编译器(csc.exe - 用于C#代码的C#编译器)或vbc.exe for VB.net代码)。您可以在此视频中查看所有IIS组件的详细架构图以及它们如何在此视频中进行交互:http://linqto.me/IISArchP1以及此视频中工作进程(w3wp.exe)内部工作方式的详细说明:http://linqto.me/IISArchP2

然后.Net运行时将暂停执行请求,等待执行编译器进程(csc.exe或vbc.exe)。如果在第一个请求进入时查看服务器的任务管理器,您实际上可以看到编译器激活。编译器将使用与用于应用程序池的凭据相同的凭据(帐户)运行。默认情况下,这是从IIS 7.5开始使用的应用程序池标识,但您可以在“高级属性”中配置自己的帐户。应用程序池。

如果编译器进程遇到错误(无论是您在代码中引入的编译错误还是其他错误),它都会将错误消息传回工作进程,这只会发出500(内部服务器错误)特定请求的状态代码返回连接客户端。因此,我们现在知道该错误来自使用相同凭据并在与w3wp.exe相同的会话中运行的csc.exe进程。现在转到在特定情况下引发的错误消息。

查看返回代码值,首先要做的是从基数10转换为基数16 - 或者HEX,我们可以使用调试器甚至是windows计算器来实现:

.formats -0n1073741502 评估表达式: 十六进制:c0000142 十进制:-1073741502 八进制:30000000502 二进制:11000000 00000000 00000001 01000010 Chars:...... B 时间:*****无效 浮点数:低-2.00008高-1。#QNAN 双倍:-1。#QNAN

然后使用工具查找十六进制错误代码,我们可以看到以下内容:

!error c0000142

错误代码:(NTSTATUS)0xc0000142(3221225794) - {DLL初始化失败}动态链接库%hs的初始化失败。这个过程异常终止。

因此,由于Dll初始化失败,csc.exe进程终止。当系统处于所谓的桌面堆内存不足时,很可能会发生这种情况。这是一种特殊类型的内存,在启动时为计算机上的帐户打开的每个会话分配。因此,使用该特定帐户的凭据运行的所有进程将共享来自为该帐户的会话分配的桌面堆的资源。

如果在相同帐户的凭据下运行的进程太多,桌面堆可能接近耗尽,因此可能无法为需要在特定进程内加载的dll提供资源。这是一篇关于如何调整桌面堆片段大小的文章:http://blogs.msdn.com/b/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx - 但我推荐的是另一种解决方案。

解决方案:

现在我们知道这个错误是由Desktop Heap耗尽产生的,一个简单的解决方案是为我们看到错误的应用程序池创建一个专用帐户。因此,工作进程和csc.exe进程将使整个桌面堆段可用于自己,从而绕过资源消耗问题。

作为最后一点,我想强调IIS应用程序池的默认配置,其中每个池在应用程序池启动时动态地由IIS分配其自己的标识(帐户),同时绕过问题,因为每个应用程序池以及它需要启动的编译器实例不需要竞争共享桌面堆的稀缺资源。

解决方案更新 - 2018年1月

编译器崩溃是由与非交互式Window Station关联的桌面的桌面堆耗尽引起的。这导致user32.dll或kernel32.dll无法正确初始化。上面提到的博客文章很大程度上解释了桌面堆是什么以及它的用途。可以说,所有IIS工作进程以及通常所有Windows服务都在与非交互式Window Station相关的桌面中运行。这意味着,从IIS工作进程或Windows服务(如消息框)中的代码生成的图形界面将不会显示在用户桌面中,该桌面与交互式会话有关。

默认情况下,属于非交互式窗口站的桌面的每个桌面堆的大小是通过注册表定义的,使用以下键: HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ SubSystems \ Windows

Windows注册表项的值如下: %SystemRoot%\ system32 \ csrss.exe ObjectDirectory = \ Windows SharedSection = 1024,20480,768 Windows = On SubSystemType = Windows ServerDll = basesrv,1 ServerDll = winsrv:UserServerDllInitialization,3 ServerDll = sxssrv,4 ProfileControl = Off MaxRequestThreads = 16 < / p>

共享部分(上面的粗体)是描述KiloBytes中桌面堆大小的部分。我们感兴趣的是第三个值(768),它是非交互式Window Station中桌面桌面堆的大小。如果更改应用程序池的帐户无法解决问题,则会增加堆的大小。我建议通过将值从默认值768增加到4864(786 + 4096 KB)来为此堆添加4 MB的内存。使用注册表编辑器进行此更改后,您将需要重新启动操作系统(重新启动Windows)以允许更改。

修改后,注册表项值应如下所示:

%SystemRoot%\ system32 \ csrss.exe ObjectDirectory = \ Windows SharedSection = 1024,20480,4864 Windows = On SubSystemType = Windows ServerDll = basesrv,1 ServerDll = winsrv:UserServerDllInitialization,3 ServerDll = sxssrv,4 ProfileControl = Off MaxRequestThreads = 16

如果有更大的桌面堆,编译器现在将拥有初始化所需的资源,并且能够执行ASP.net页面的编译。

作者:Paul Cociuba - ASP.net工程师