错误处理和调试
一、跟踪调试:
Visual Studio 调试器:
功能强大,可以观察程序运行时的行为并确定逻辑错误的位置,可以中断(挂起)程序的执行以检查代码,计算和编辑程序中的变量并查看寄存器,查看从源代码创建的指令,以及查看应用程序所占用的内存空间。使用“编辑并继续”可以在调试时对代码进行修改,然后继续执行。
(一)非中断0(正常)模式下调试:
1.ASP.NET非中断模式下的调试
使用Response.Write()和Response.End()两个函数调试得到操作的额外反馈。
启用调试模式:
(1)项目程序
解决方案资源管理器 右击 ->属性页->启动选项->调试器:ASP.NET(勾选)
(2)Web.Config配置文件
ASP.NET将Microsoft IIS配置为防止浏览器直接访问web.config配置文件,否则HTTP访问错误403(禁止)
可以以任何标准文本编辑器(.txt)或Xml分析器打开Web.config并予以修改:
查找到<compilation debug="true" ></compilation> 设置debug属性为true启用调试。
如果web.config文件指定在aaa文件目录下而且debug="true",那么aaa文件夹中或aaa的任何子文件夹中的所有应用程序都将继承这一设置置.
【注意】启动调试模式将极大地影响ASP.NET应用程序的性能。切记,在部署发布版本的应用程序或进行性能度量之前要禁用调试模式(debug="false")
2.WinForm非中断模式下的调试
使用 MessageBox.Show() 函数调试来得到操作的额外反馈。
try{}
catch(Exception ex)
{ MessageBox.Show(ex.Message);} //出现异常时在消息框中弹出提示
(二)中断模式下调试:(可暂停程序的执行)
1.ASP.NET中断模式下的调试(断点跟踪模式)
在运行应用程序时暂停执行,进入中断,但暂停的位置随意。为了更好地控制程序运行停止的位置,可以在程序调试过程中设置断点。
断点:可以让程序一直执行,然后碰到断点时开始调试。
修改断点行为的属性:
HitCount 能够确定在调试器中断执行之前命中断点的次数
Condition 表达式,确定断点是命中还是跳过,当调试器到达该断点时它会计算条件的值,只有当条件满足时,断点才会命中。可以在某个位置断点处设置条件,只有当条件为真时才会中断执行。
Action 命中断点时应执行的操作。默认时,调试器中断执行,但是可以选择打印一条消息或者运行一个Visual Studio宏。如果选择打印消息而不是中断,则断点效果与Trace语句非常类似,这种断点称跟踪点。
Filter 提供了一种为断点指定进程或线程的方法。
断点属性:条件、命中次数、删选器、命中条件(跟踪点)
调试窗口:监视、局部变量、调用堆栈、即时窗口
调试方法:启动调试(F5)、逐过程(F10)、逐语句(F11)、跳出(Shift+F11)
跟踪点(trace):与断点关联的自定义操作断点。命中跟踪点时执行指定跟踪点操作而不是或不单是中断服务程序执行。使用跟踪点无需修改代码,只有在调试器中工作时,跟踪点才起作用。任何断点都可以转换为跟踪点(命中条件勾选打印消息或运行宏)。在打印消息和运行宏中可以在其中输入自定义的操作。
消息文本框中可以使用DebuggerDisplayAttribute语法包括编程信息。例如:
In function'{$FUNC}',on thread'{$TID}'
Used variable:{varName},function name:{functionName($FUNC)}
可以使用在“命中断点时”对话框中显示任何关键字(如Function:$FUNCTION,Thread:$TID $TNAME),还可以使用没有在该对话框中显示的其他两个关键字:用于插入当前CPU计数的$TICK和用于插入当前文件位置的$FILEPOS.
2.WinForm中断模式下的调试(断点跟踪模式):同ASP.NET。
二、错误处理:
(一)ASP.NET中的错误处理:
1.服务器故障排除
a.Web服务器配置不正确,错误信息显示如下:
The Web server is not configured correctly.See help for common configuration errors.Running the web page outside of the debugger may provide further information.
【产生原因】(1)没有足够的IIS连接;(2)调试ASP.NET项目,检查DEBUG谓词是否与.aspx关联;(3)检查在IIS中该网站是否已配置为应用程序:
开始->程序->管理工具->Internet信息服务 ->你的网站->右击默认网站->属性->“主目录”选项卡->应用程序设置,如果找到按钮是“删除”,则网站已经配置为 应用程序,如果找到的按钮是“创建”,单击该按钮将网站配置为应用程序。->确定。
(4)如果正尝试调试ATL Web应用程序,则应验证DEBUG谓词是否与ISAPI扩展名关联
b.Web服务器已经被锁定,正在阻止DEBUG谓词
【产生原因】运行IIS防范工具并安装\激活了URLScan,单步执行Web应用程序或XML Web Services失败,这种情况下会禁止IIS接收DEBUG谓词。
【解决方法】请安装IIS6.0;在系统目录中找到Urlscan.ini文 件,通常在下面的目录中:C:\WINDOWS\System32\Inetsrv\urlscan->创建此文件的副本并将其命名为 Urlscan.old。->使用记事本打开Urlscan.ini文件的原始副本。->在Urlscan.ini中找到 [AllowVerbs]节,将“DEBUG”添加到[AllowVerbs]节中,如果在[AllowVerbs]节中找到“;DEBUG”,请移除分 号,以取消谓词的注释状态-> 找到[DenyVerbs]节,如果DEBUG出现在[DenyVerbs]节中请删除它。->保存该文件。->重新启动服务器或IIS。
c.“未能创建Windows用户标记”错误
【产生原因】在Web.config文件中,将网站配置为基于应用程序的模拟(使用固定帐户模拟)并且运行Web服务器的帐户没有“作为操作系统的一部分”特权,也称“受信任的计算基(TCB)特权。
【解决方案】使用以下语法,可在Web.config文件中将网站配置为模拟某个特定账户:
<identity impersonate="true" userName="User1"password="Pwd"/>
启动ASP.NET Development Server的进程必须必须具有TCB特权,因此如果网站配置为执行模拟,则必须向运行Web服务器的账户授予TCB特权。(一般TCB特权授予尽量少的账户,如果没有TCB特权就无法使用ASP.NET Development Server,可以考虑使用IIS来测试网站,以免向账户授予不必要的特权)
d.“无法显示页”错误(502错误)
【产生原因】浏览器无法解析包含“localhost”和端口号的URL(如:http://localhost:8080/ExampleWebSite/Default.aspx )。ASP.NET Development Server以独占方式使用localhost,在默认情况下对每个请求都使用随机选择的端口号。
【解决方案】跳过用于本地请求的代理服务器。
e.“连接被拒绝”错误
10061-Connection Refussed
Internet Security and Acceleration Server
【产生原因】计算机在受Internet Security and Acceleration Server(ISA Server)保护的网络上运行并且满足了以下条件之一:客户端未安装防火墙、Internet Explorer中的Web代理配置不正确、使用IIS时不会发生此错误,因为IIS使用80端口,而ISA Server和其他防火墙产品允许访问80端口,但是ASP.NET Development Server随机选择端口,而ISA Server防火墙产品会阻止对大多数端口的访问。
【解决方案】(1)安装防火墙客户端软件,比如ISA客户端。(2)修改Internet Explorer中的Web代理连接设置,以跳过用于本地地址的代理服务器。
f.“超过BIOS限制”错误
【产生原因】使用的是文件系统Web应用程序,而该应用程序的文件在远程计算机上,如果运行的是Windows 2000或Windows XP操作系统,极有可能发生此错误。
【解决方案】如果运行的是WinXP系统,通过关闭远程计算机上的现有共享资源(包括终端服务器会话),可以避免此错误。(Windows XP被配置为使用固定的最大并发网络请求数),如果可行,还可以将Web应用程序文件复制到本地计算机,在本地计算机上测试该应用程序。
g.不能使用静态文件
【产生原因】文件系统网站中,静态文件(如图像和样式表)受到ASP.NET授权规则的影响。
【解决方案】将网站部署到运行IIS的服务器上运行(IIS提供静态文件而不是用授权规则)。
2.Web应用程序的IIS设置:
打开IIS->右击默认网站属性->选择“目录安全性”选项卡->匿名访问和身份验证控制下“编辑”->勾选“启用匿名访问”和“Windows身份验证”->确定
对于ASP.NET应用程序,请确保应用程序的虚拟文件夹中具有在“Internet信息服务(IIS)”中设置的应用程序名称,具体设置如下:
默认网站属性->“主目录”选项卡->本地路径:浏览你的ASP.NET应用程序的根目录;应用程序设置下,键入包含应用程序的根目录名称->“ASP.NET”选项卡->验证是否指定了正确的ASP.NET版本->确定->确定。
3.ASP.NET异常处理:
(1)启用ASP.NET异常调试和“仅我的代码”:
“调试”菜单->异常->Common Language Runtime Exceptions公共语言运行库异常 ,选择“引发”或“用户未处理”项。
(2)ASP.NET异常处理最佳做法:
在可能引发异常的代码周围:try……catch……finally,例如:如果应用程序调用XML Web services或直接调用SQL Server,则应该将该代码置于try……catch块中,因此此过程中可能会发生大量异常。
(二)WinForm错误处理:
1.处理异常最佳做法:
(1)知道何时设置try/catch块:
可以编程方式检查可能发生的条件,而不使用异常处理,而在其他情况下,使用异常处理捕捉错误条件是适当的。比如:检查连接是否关闭可使用if语句,如果连接未关闭,则使用关闭方法而不是引发异常。
if(conn.State!=ConnectionState.Close)
conn.Close();
或
try
{conn.Close();}
catch(InvalidOperationException ex)
{//处理错误代码}
(2)使用try/finally,try语句生成异常,catch语句从中心位置处理异常,finally语句关闭或释放资源。
(3)以“Exception”这个词作为异常类名的结尾,例如:
public class MyFileNotFoundExcption:ApplicationException
{ //将程序集放在两个应用程序域共享的公共应用程序集中,如果两个应用程序域不共享一个公用应用程序集,则用“强名称”给包含异常信息的程序集签名,并将其部署到全局程序集缓存中。
}
(4)在C#中创建异常类时,至少使用三个公共构造函数:
using System;
public class EmployeeListNotFoundException:Exception
{ public class EmployeeListNotFoundException()
{}
public EmployeeListNotFoundException(string message):base(message)
{}
public EmployeeListNotFoundException(string message,Exception inner):base(message,inner)
{}
}
(5)用户看到的错误信息从本地化描述字符串派生,而不是异常类派生
(6)使用语法上的错误信息(包括结束标点符号),每个句子都应以句号结尾
(7)对常见的错误情况返回空NULL,例如:如果没有找到文件,则File.Open返回空;但如果文件被锁定,则引发异常。
(8)对类的设计应在正常使用中从不引发异常,如FileStream类公开另一种确定是否已到达文件尾的方法,这避免了在读取超过文件尾时引发的异常:
class FileRead
{ void Open()
{ FileStream fs=File.Open("myfile.txt",FileMode.Open);
byte b;
while((b==fs.ReadByte())!=true) //while语句来判断是否文件还可读?
{ //要执行的操作}
}
}
(9)如果根据对象的当前状态、属性集或方法调用不适当,则引发InvalidOperationException.
(10)如果传递无效的参数,则引发ArgumentException或从ArgumentException派生的类。
(11)堆栈跟踪从引发异常语句开始到捕捉异常的Catch语句结束,当决定在何时放置Throw语句时需考虑。、
(12)使用异常生成器方法(类从其实现的不同位置引发同一异常是常见情况,使用帮助器方法创建异常并就爱那个其返回),具体如下:
class File
{ string fileName
public byte[] Read(int bytes)
{ if(!ReadFile(handle,bytes))
throw NewFileOException();
}
FileException NewFileOException()
{string description=" ";
return new FileException(description);}
}
}
2.WinForm中的异常处理:
(1)try……catch语句:
try{//执行可能引发错误的操作}
catch(异常类型参数) { //异常处理 }
【注意】catch 可以不加参数捕获任何类型的异常,还可以接受从System.Exception派生的对象参数,这样他就处理特定的异常了,比如 catch(InvalidCastException e){}.在同一个try-catch语句中可以使用一个以上的特定catch子句,这种情况下catch子句的顺序很重要,因为会按顺序检查catch 子句,将先捕获特定程度较高的异常,而不是特定程度较小的异常。在catch语句中还可以使用throw语句再次引发已经由catch语句捕获的异常。 throw(e); 表示抛出异常。
catch(InvalidCastException e)
{throw(e);}
或
catch
{throw;}
(2)try……finally语句:
避免将try……catch用于清理代码,在书写规范的异常代码中,try-finally使用比try-catch更多。finally子句即可执行清理代码,如果分配了昂贵或有限的资源(如数据库连接或流),则应将释放这些资源的代码放置在finally块中。
(3)try-catch-finally 语句:
在try块中获取并使用资源,在catch块中处理异常情况,并在finally块中释放资源
(4)throw语句:
用于输出在程序执行期间出现反常情况(异常)的信号,通常throw语句同try-catch或try-finally语句一起使用。当引发异常时,程序查找处理此异常的catch语句,也可以用throw语句重新引发异常(抛出异常)
【注意】保留异常调用堆栈的最佳方法:捕捉不能够再次引发异常,使用空引发。例如:
public void DoWork(Object anObject)
{//可能引发异常的地方
if(anObject==null)
{throw new ArgumentNullException("anObject","Specify a non-null argument.");}
}
public void MethodWithBadCatch(Object anObject)
{ try
{DoWork(anObject);}
catch(ArgumentNullException e)
{System.Diagnostics.Debug.Write(e.Message);
throw e;
}
}

浙公网安备 33010602011771号