摘要:因为帐户的配置和相互作用可以在多个不同步骤中引起中断,所以调试 ASP.NET 可能是件棘手的事情。本文概括论述与调试 ASP.NET 应用程序相关的常见问题,列举错误示例并解释如何解决这些问题。
本页内容
简介 | |
ASP.NET调试。 | |
常规调试 | |
因果性调试:Web 服务客户端和 Web 服务之间的步骤 | |
远程调试 |
简介
在过去的几个月中,我曾与许多存在调试问题的用户一起工作,他们之中有一部分来自 Microsoft 内部。我发现,如果用户能得到正确的诊断,则很多常见的错误和问题便迎刃而解。因此,我写了这篇文章,旨在向用户提供在使用调试器时能帮助他们解决问题的信息。
本文档包含:
• |
错误消息对话框或错误情况描述 |
• |
上述错误的原因。 |
• |
上述问题的解决方法。 |
在此,我对 VCS 调试器团队和帮助我完成本文及向我提供精彩反馈的人士表示感谢。
ASP.NET调试。
注 如果在本部分中找不到需要的错误消息,请查看处理常规调试问题部分或处理远程调试问题部分。
消息:无法在 Web 服务器中启动调试。
图 1. 无法启动调试错误消息
原因 1:未将 IIS 应用程序配置为使用 Integrated Windows Authentication。确保已选中“Authentication Method”对话框中的 Integrated Windows Authentication 复选框,如图 2 所示。
图 2. 启用集成身份验证
原因 2:检查 IIS 的 Enable HTTP Keep Alive 选项。如果它是关闭的,则可能需要将其打开,再尝试调试。
消息:您没有调试服务器的权限。
图 3. 无调试权限
原因 1:确保已启用 Integrated Windows Authentication。可能的原因是仅为 IIS 的 Directory 安全启用了 Basic authentication。
原因 2:如果您在使用 Integrated Windows Authentication,则需要确保您的用户帐户能够完全控制 IIS 的目录。
原因 3:如果使用完整的机器名(如 machinename.domainname.something)创建 Web 项目,则该 Web 站点会被识别为 Internet 站点。因此,Internet Explorer 的默认设置将对登录行为产生影响。在这种情况下,您需要使用当前帐户在具有 IE 设置的“Internet”区域启用登录。
然而,这不是 Internet Explorer 的默认设置,因此最好仅使用机器名来创建项目,将图 4 用作 Security Settings 的指南。
图 4. 设置 Internet Explorer 身份验证
消息:发送调试 HTTP 请求时发生服务器端错误。
图 5. 调试期间的服务器端错误
原因 1:Web 应用程序没有应用程序名。为此,请使用 IIS MMC 来检查 Web 项目的属性,确保 Web 项目具有应用程序名。当图 6 中的红色轮廓出现时,应该出现应用程序名。
图 6. 设置应用程序名
原因 2:如果使用的是 NTFS 文件格式,则确保“aspnet”具有“wwwroot”或虚拟目录文件夹上的适当权限,才能访问和写入这些文件夹。
消息:没有对项目进行配置以接受调试。
图 7. 未针对调试配置项目
如果出现这一错误消息,则需要针对调试配置 Web。为此,需要在 web.config 文件中设置 debug = true。此文件位于 Web 项目文件夹中。
您可以启动调试,同时不出现错误消息,但是不能到达断点。
您使用 F5 键启动了调试,看起来好像正确启动了调试并且也正确启动了 Internet Explorer,但是您不能到达代码隐藏的代码中的断点。
原因 1: 在项目属性中未启用 Asp.net 调试。按照图 8 所示将该项设置为 True。
图 8. 启用 ASP.NET 调试
在 VB 项目中,UI 有所不同,但可以轻松地识别等效项。
原因 2:请确保使用匹配的调试符号文件加载期望的 DLL。可以使用 Modules 窗口来检查这一点。
消息:未正确安装调试器。
图 9. 未正确安装调试器
如果看到这一问题,请在 Console Application 项目中检查调试功能。如果控制台应用程序项目显示如图 10 所示的错误消息,则表示未正确安装 .NET Framework 应用程序。
图 10. 无法启动调试
需要通过执行“regsvr32 mscordbi.dll”来手动注册“mscordbi.dll”。
消息:服务器不支持对 ASP.NET 或 ATL 服务器应用程序的调试。
图 11. 无法启动调试
如果您在机器上安装了 Windows XP Pro 或 Windows 2000 Pro,则可能需要考虑 Visual Studio 7 和 IIS 之间的安装顺序。如果在 Visual Studio 7 之后安装 IIS,则会发生这一错误。在这种情况下,请使用“aspnet_regiis.exe –i”注册“aspnet_isapi.dll”。
消息:访问被拒绝。检验您是否是管理员或某个组成员。
图 12. 访问被拒绝
您可能不是该计算机上 Debugger Users 组的成员。将您的用户帐户添加到计算机上的 Debugger Users 组中即可解决此错误。
要将您的用户帐户添加到 Debugger Users 组中,需要执行以下操作:
1. |
作为 Administrator 登录。 |
2. |
运行 Administrator tools 中的 Computer management。 |
3. |
选择 Local users and groups\groups 节点。 |
4. |
双击右边窗格中的 Debugger Users 组。 |
5. |
单击 Debugger users properties 对话框中的 Add 按钮。 |
6. |
键入用户帐户并单击 OK。 |
消息:无法启动 ASP.NET 或 ATL 服务器调试。
图 13. 未安装ASP.NET 或 ATL
原因 1:您可能安装了 IIS Lockdown 工具。如果这样,则查找 urlscan.ini 文件,并将 DEBUG(区分大小写)添加到 [allowverbs] 部分中。
原因 2:如果将域控制器用作服务器,并且项目是使用机器名(非完整域名)创建的,则可能需要将项目的 URL 更改为完整域名。
原因 3:如果将 IIS 设置为使用专用 IP(例如 Web site identification,可以在 IIS MMC 的 IIS 设置中找到这一选项),则可能看到这条错误消息。在这种情况下,需要更改项目名,直接使用 IP 地址。对于现有项目,需要更改项目以使用 IP 地址,而不用通过编辑 .sln 文件和 .webinfo 文件使用机器名。
原因 4:web.config 文件的 中的值太大。默认单位是千字节而非字节,因此如果更改此数字,使用了错误的单位,则可能导致调试问题。
消息:访问被拒绝。
图 14. 访问被拒绝
原因:您可能是 Debugger Users 组的成员,但是您不具有调试 aspnet 辅助进程的权限,因为您不是 aspnet 用户帐户或 Administrators 组的成员。将您的用户帐户添加到机器上的 Administrators 组即可解决此问题。
无法使用包括文件进行调试
在 ASPX 中,无法使用包括文件进行调试。将旧的 ASP 项目转换为 ASPX 时,往往产生包括文件。
如果通过 包括文件,则可能无法正确调试该包括文件。您需要使用 来代替。
更改密码后,需要注销/登录才能进行 ASP.NET 调试。
更改密码后,需要注销,然后再登录才能正确进行 ASP.NET 调试。
安装 Windows2000 SP4 后,ASP.NET 调试不能运行,同时显示消息“访问被拒绝”。
此问题的解决方法是,使用 regsvr32 –i aspnet_isap.dll 重新注册 aspnet_isap.dll。
仅在首次加载页面时遇到断点。
针对这一特定问题,可能存在多种原因,但是最大的可能性是您在 web.config 文件中设置了页面缓存选项。
如果在 web.config 中看到类似于 的内容,则需要将值设置为“False”,以关闭 Web 页面缓存。更改该设置并刷新页面后,可能遇到断点。
您需要共享 Web 服务器以进行调试,但是不想让其他用户成为计算机管理员。
在 Visual Studio .NET 中,以下二者可以确定用户是否可以进行调试。其中之一是 Debugger Users 组,另一个是用户权限,如管理员、Power User 或 SEDebug。
Debugger Users 组确定用户是否可以访问 VS 调试组件(主要是 MDM-Machine Debug Manager,Visual Studio 的一部分),所以成为该组的成员意味着保证可以访问 MDM。因此在这一点上,您可以调试开放进程并查看机器上的进程列表。
不过在此之后,您是否可以调试其他用户的进程取决于您的权限。例如,如果您想调试别人的本地进程,则需要具有 SEDebug 权限.针对其他用户的托管进程,您应该是该机器上的管理员,才有权进行调试。
因为存在这一限制,所以在您的方案中,应该授予学生管理员权限。否则,默认情况下无法对 ASP.NET 辅助进程进行调试。
我们有一种变通方法。Cassini 是一个独立的小型 ASP.NET 服务器。对学生来说,他们可以使用 Cassini 进行开发,稍后将开发结果部署到实际服务器上来提交结果。Cassini 位于
常规调试
这些案例基于 Console application 项目类型。
消息:无法启动调试。
图 15. 无法启动程序
导致图 15 中所示问题的原因是没有正确注册 mscordbi.dll。此问题的补救办法是手动注册该文件。
消息:无法启动调试。访问被拒绝。
图 16. 拒绝访问错误消息
确保正确启动 Machine Debugger Manager 服务,并且确保您是 Debugger Users 或 Administrators 的成员。
我可以启动托管调试,但是 PDB 不加载,并且不能遇到任何断点。
如果正确启动了调试器,但不能遇到任何断点,则您可能需要检查 diasymreader.dll 的安装。可能没有注册该文件。要注册该文件,需要执行以下操作:
regsvr32 \diasymreader.dll
托管调试不运行
在进程创建 CLR 对象前,以 CLR 模式连接本地进程。托管调试不运行。
解决方案 1:在进程中使用了 CLR 代码后再连接进程。
解决方案 2:以 InterOp 模式连接进程。在这种情况下,不必在调用 CLR 代码之后再连接进程。
托管调试器不响应
使用托管代码启动调试时,调试器不响应。
解决方案:确保已停止并禁用 .NET FrameworkSupport 服务(仅停止该服务还不够)。
如果没有运行 .NET FrameworkSupport 服务,则禁用 IIS admin 服务。
使用 C# 代码单步调试不正确
考虑以下代码:
string someStr; someStr = "SomeValue"; if(someStr == null) Console.WriteLine("what's up?"); try { } catch(Exception e) { }
如果使用此代码,则会看到遇到“if”语句时,指令指针将移动到“if”语句体 (Console.WriteLine("what's up?");)。
这不是一个调试器 bug,而是一个众所周知的 try catch 块调试信息问题。请参见以下调试器中 try catch 块示例的反汇编代码。
if(someStr == null) a cmp dword ptr [ebp-18h],0 e jne C Console.WriteLine("what's up?"); mov ecx,dword ptr ds:[01C50070h] call dword ptr ds:[02F0257Ch] c jmp catch(Exception e) e mov dword ptr [ebp-1Ch],eax call C0846 jmp } nop
值没有匹配时,指令指针移动到 0000003c jmp 行,但是该行已经错误地与“if”语句体相匹配。当代码功能正确时,显示就不正确了。
因果性调试:Web 服务客户端和 Web 服务之间的步骤
无法从 Web 服务客户端到 Web 服务设置调试
默认设置不允许从 Web 服务客户端进入 Web 服务。它的运行方式类似 step-over。
ASPNET 辅助进程(aspnet_wp.exe 或 w3wp.exe)在“aspnet”或“network service”用户帐户之下运行,而这些帐户没有通过 DCOM 访问 MDM 的权限。因此,需要将这些帐户添加到 Debugger Users 组中。
启用 Web 服务模拟后,无法再使用因果性步骤。
使用“web.config”为 Web 服务启用模拟时,不能从 Web 服务客户端代码进入 Web 服务代码。因为,它的运行方式类似于 step over。
您需要执行以下操作来更正客户端和服务之间的步骤。
• |
关闭 IIS 中的 Anonymous access。 |
• |
更改客户端代码,将凭据设置为 Web 服务,如下所示: |
• |
Service1 obj = new Service1(); |
• |
obj.Credentials = System.Net.CredentialCache.DefaultCredentials; |
在此之后,您将能够从客户端进入 Web 服务。
这些操作是必需的,因为当您进入 Web 服务时,某些 .NET Framework 组件需要使用系统级调试器组件 (MDM) 来共同创建它。如果不能提供正确的凭据,则此步骤将失败。如果没有这些正确的凭据,“step into”的运行将类似于“step over”。
调试器挂起
如果 Web 服务客户端代码在 STA (Single Thread Apartment) 模型中运行,并且它在等待异步调用完成,如下所示:
Service1 obj = new Service1(); System.IAsyncResult ar = obj.BeginHelloWorld(new System.AsyncCallback(Class1.Handle),obj); while(ar.IsCompleted != true) { System.Threading.Thread.Sleep(1000); }
则调试器将挂起。发生此挂起操作,原因在于调试器中的代码已锁定一个调试器组件。解决方案 1 是更改代码以使用与事件或 mutex 同步的线程。另一个解决方案是注销 csm.dll。第二个解决方案禁用 causality 步骤(从 Web 服务客户端代码到 Web 服务方法的步骤)。您可能需要手动连接 aspnet_wp.exe 才能调试 Web 服务。
远程调试
无法查看远程机器上的任何进程
确保在远程机器上安装了 Remote full debug 设置,并且您是 Debugger Users 组的成员。
因 RPC 问题而无法连接到远程机器
以下信息摘自 Mike Clay 撰写的 KB 文章。
如果通过“Processes”对话框连接到远程机器上时看到以下错误消息:
Error while trying to run project: Unable to start debugging on the web server. Not enough storage is available to complete this operation.
或者在进行 ASP.NET 调试期间看到这一消息:
Error while trying to run project: Unable to start debugging on the web server. Unable to map the debug start page URL to a machine name.
则确保 RPC 在您的机器与远程机器之间正确运行。下面的行为可能导致 RPC 问题:
• |
通过防火墙进行调试。Microsoft 不建议或支持通过防火墙的远程 ASP.NET 调试。解决此问题最好的方式是,使用“终端服务”登录远程服务器并在本地进行调试。 |
• |
RPC 的一种常见故障是无力解析远程机器名。RPC 依靠名称解析在计算机之间通信。如果未能将远程服务器机器名解析为正确的 IP 地址,则可能发生错误。 |
• |
RPC 通信只能单向流动,另一个方向却不行。RPC 通信必须能够从用于调试的机器到达远程服务器,并从远程服务器返回用于调试的机器,这样才能成功进行远程调试。确保以双向方式启用 RPC 通信。 |
要分析 RPC,可以使用 RPCPing 工具。
远程调试工作组中的机器失败
当您的两台 Windows XP Pro 机器都不在域中但在工作组中时,将发生这种情况。在它们之间进行远程调试时,您根本无法访问远程机器。
在工作组环境中,您需要确保两台机器具有相同的用户帐户名和相同的密码。否则,DCOM 进行身份验证时将失败。
另外,在 Windows XP Pro 上,将 Sharing and security model for local accounts 的默认安全设置设置为现在允许共享。下面是更改此设置的步骤:
1. |
运行管理员工具中的 Local Security Settings。 |
2. |
选择 Security settings\Local policies\Security 选项。 |
3. |
将 Network access : Sharing and Security model for local accounts 从 Guest only - local users authenticate as Guest 更改为 Classic - local users authenticate as themselves。 |
4. |
重新启动计算机。 |
应该将此更改应用于进行远程调试的两台机器。
更改设置后,即可使用同一名称的用户帐户在两台机器上进行远程调试。请确保每台机器上的用户帐户都具有密码。在某些情况下,没有实际密码机器不能运行。
然而,因为更改了安全模型的默认设置,所以可能公开下面的内容:
• |
意外的文件共享 |
• |
意外的 DCOM 组件共享。 |
在进行这一更改之前,从远程机器到您的机器的任何种类的连接都是以 Guest 身份进行的;但更改后,他/她即可接受使用本地用户帐户的身份验证。因此,在调试案例中,如果将一个文件夹或 DCOM 对象共享出来,其他机器上的任何匹配用户(具有相同用户名和相同密码)都可能可以访问您的共享对象。
我极力建议,如果您要使用这一变通方法,则请确保所有用户帐户都具有强密码,否则应该设置一个网络孤岛来调试机器,以防止恶意攻击。