2023年12月30日发(作者:)

这是因为.NET Framework 1.0 和 1.1 这两个版本对许多未处理异常(例如,线程池线程中的未处理异常)提供支撑,而 Framework 2.0 版中,公共语言运行库允许线程中的多数未处理异常自然继续。在多数情况下,这意味着未处理异常会导致应用程序终止。

一、C/S 解决方案(以下任何一种方法)

1. 在应用程序配置文件中,添加如下内容:

2. 在应用程序配置文件中,添加如下内容:

3. 使用Exception事件在异常导致程序退出前截获异常。示例如下:

[SecurityPermission(, Flags =

lAppDomain)]

public static void Main(string[] args)

{

Exception += new

ThreadExceptionEventHandler(1_UIThreadException);

andledExceptionMode(xception);

ledException += new

UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

(new ErrorHandlerForm());

}

// 在主线程中产生异常

private void button1_Click(object sender, rgs e)

{

throw new ArgumentException("The parameter was invalid");

}

// 创建产生异常的线程

private void button2_Click(object sender, rgs e)

{

ThreadStart newThreadStart = new ThreadStart(newThread_Execute);

newThread = new Thread(newThreadStart);

();

}

// 产生异常的方法

void newThread_Execute()

{

throw new Exception("The method or operation is not implemented.");

}

private static void Form1_UIThreadException(object sender, ThreadExceptionEventArgs t)

{

DialogResult result = ;

try

{

result = ShowThreadExceptionDialog("Windows Forms Error", ion);

}

catch

{

try

{

("Fatal Windows Forms Error",

"Fatal Windows Forms Error", etryIgnore,

);

}

finally

{

();

}

}

if (result == )

();

}

// 由于 UnhandledException 无法阻止应用程序终止,因而此示例只是在终止前将错误记录在应用程序事件日志中。

private static void CurrentDomain_UnhandledException(object sender,

UnhandledExceptionEventArgs e)

{

try

{

Exception ex = (Exception)ionObject;

string errorMsg = "An application error occurred. Please contact the adminstrator

" +

"with the following information:/n/n";

if (!Exists("ThreadException"))

{

EventSource("ThreadException", "Application");

}

EventLog myLog = new EventLog();

= "ThreadException";

ntry(errorMsg + e + "/n/nStack Trace:/n" +

race);

}

catch (Exception exc)

{

try

{

("Fatal Non-UI Error",

"Fatal Non-UI Error. Could not write the error to the event log. Reason:

"

+ e, , );

}

finally

{

();

}

}

}

private static DialogResult ShowThreadExceptionDialog(string title, Exception e)

{

string errorMsg = "An application error occurred. Please contact the adminstrator " +

"with the following information:/n/n";

errorMsg = errorMsg + e + "/n/nStack Trace:/n" + race;

return (errorMsg, title, etryIgnore,

);

}

二、B/S 解决方案(以下任何一种方法)

1. 在IE目录(C:/Program Files/Internet Explorer)下建立文件,内容如下:

2. 不建议使用此方法,这将导致使用 framework 1.1 以后版本的程序在IE中报错。

建立同上的配置文件,但内容如下:

3. 这个比较繁琐,分为三步:

⑴. 将下面的代码保存成文件,文件名为,路径是C:/Program Files/Microsoft Visual Studio 8/VC/

using System;

using stics;

using ization;

using ;

using pServices;

using ;

using ing;

using ;

namespace WebMonitor {

public class UnhandledExceptionModule: IHttpModule {

static int _unhandledExceptionCount = 0;

static string _sourceName = null;

static object _initLock = new object();

static bool _initialized = false;

public void Init(HttpApplication app) {

// Do this one time for each AppDomain.

if (!_initialized) {

lock (_initLock) {

if (!_initialized) {

string webenginePath =

e(timeDirectory(), "");

if (!(webenginePath)) {

throw new

Exception((antCulture,

"Failed to locate

at '{0}'. This module requires .NET Framework 2.0.",

webenginePath));

}

FileVersionInfo ver =

sionInfo(webenginePath);

_sourceName = (antCulture,

" {0}.{1}.{2}.0",

jorPart,

norPart, ildPart);

if (!Exists(_sourceName)) {

throw new

Exception((antCulture,

"There is no

EventLog source named '{0}'. This module requires .NET Framework 2.0.",

_sourceName));

}

ledException += new

UnhandledExceptionEventHandler(OnUnhandledException);

_initialized = true;

}

}

}

}

public void Dispose() {

}

void OnUnhandledException(object o, UnhandledExceptionEventArgs e) {

// Let this occur one time for each AppDomain.

if (ge(ref _unhandledExceptionCount, 1) != 0)

return;

StringBuilder message = new StringBuilder("/r/n/r/nUnhandledException

logged by :/r/n/r/nappId=");

string appId = (string) a(".appId");

if (appId != null) {

(appId);

}

Exception currentException = null;

for (currentException = (Exception)ionObject; currentException !=

null; currentException = xception) {

Format("/r/n/r/ntype={0}/r/n/r/nmessage={1}/r/n/r/nstack=/r/n{2}/r/n/r/n",

e().FullName,

e,

race);

}

EventLog Log = new EventLog();

= _sourceName;

ntry(ng(), );

}

}

}

⑵. 打开Visual Studio 2005的命令提示行窗口

输入Type -k 后回车

输入Type csc /t:library /r:, /keyfile:

后回车

输入 /if 后回车

输入ngen install 后回车

输入gacutil /l UnhandledExceptionModule后回车并将显示的”强名称”信息复制下来

⑶. 打开应用程序的文件,将下面的XML加到里面。注意:不包括”[]”,①可能是添加到之间。

type="ledExceptionModule, [这里换为上面复制的强名称信息]" />

三、微软并不建议的解决方案

打开位于 %WINDIR%//Framework/v2.0.50727 目录下的

文件,将属性 legacyUnhandledExceptionPolicy 的 enabled 设置为 true

四、跳出三界外——ActiveX

ActiveX 的特点决定了不可能去更改每个客户端的设置,采用 B/S 解决方案里的第 3

种方法也不行,至于行不通的原因,我想可能是因为 ActiveX 的子控件产生的异常直接

被 CLR 截获了,并没有传到最外层的 ActiveX 控件,这只是个人猜测,如果有清楚的朋友,还望指正。

最终,我也没找到在 ActiveX 情况的解决方法,但这却是我最需要的,无奈之下,重新检查代码,发现了其中的问题:在子线程中创建了控件,又将它添加到了主线程的 UI

上。

以前遇到这种情况,系统就会报错了,这次居然可以蒙混过关,最搞不懂的是在

framework 2.0 的 C/S 结构下也没有报错,偏偏在 IE(ActiveX) 里挂了。唉,都是宿主惹的祸。

嘿嘿,不想承担责任,就得找个顶罪的 :)

注:① 之所以说可能,是因为 MSDN 上没有写具体加到配置文件的哪个位置,我从其它的配置文件中看到类似的信息加到了里,因为这种方案没能解决我的问题,所以我并不确定是不是加到这个位置。