C# CLR20R3 程序終止的幾種解決方案 【轉】


【轉】CLR20R3 程序終止的幾種解決方案

 

 這是因為.NET Framework 1.0 和 1.1 這兩個版本對許多未處理異常(例如,線程池線程中的未處理異常)提供支撐,而 Framework 2.0 版中,公共語言運行庫允許線程中的多數未處理異常自然繼續。在多數情況下,這意味着未處理異常會導致應用程序終止。

 

一、C/S 解決方案(以下任何一種方法)
1. 在應用程序配置文件中,添加如下內容:
<configuration>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="true" />
  </runtime> 
</configuration>

 

2. 在應用程序配置文件中,添加如下內容:
<configuration>
  <startup>
    <supportedRuntime version="v1.1.4322"/>
  </startup>
</configuration>

 

3. 使用Application.ThreadException事件在異常導致程序退出前截獲異常。示例如下:
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
public static void Main(string[] args)
{
    Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    Application.Run(new ErrorHandlerForm());
}

 

// 在主線程中產生異常
private void button1_Click(object sender, System.EventArgs e)
{
    throw new ArgumentException("The parameter was invalid");
}

 

// 創建產生異常的線程
private void button2_Click(object sender, System.EventArgs e)
{
    ThreadStart newThreadStart = new ThreadStart(newThread_Execute);
    newThread = new Thread(newThreadStart);
    newThread.Start();
}

 

// 產生異常的方法
void newThread_Execute()
{
    throw new Exception("The method or operation is not implemented.");
}

 

private static void Form1_UIThreadException(object sender, ThreadExceptionEventArgs t)
{
    DialogResult result = DialogResult.Cancel;
    try
    {
        result = ShowThreadExceptionDialog("Windows Forms Error", t.Exception);
    }
    catch
    {
        try
        {
            MessageBox.Show("Fatal Windows Forms Error",
                "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
        }
        finally
        {
            Application.Exit();
        }
    }

    if (result == DialogResult.Abort)
        Application.Exit();
}

 

// 由於 UnhandledException 無法阻止應用程序終止,因而此示例只是在終止前將錯誤記錄在應用程序事件日志中。
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    try
    {
        Exception ex = (Exception)e.ExceptionObject;
        string errorMsg = "An application error occurred. Please contact the adminstrator " +
            "with the following information:/n/n";

        if (!EventLog.SourceExists("ThreadException"))
        {
            EventLog.CreateEventSource("ThreadException", "Application");
        }

        EventLog myLog = new EventLog();
        myLog.Source = "ThreadException";
        myLog.WriteEntry(errorMsg + ex.Message + "/n/nStack Trace:/n" + ex.StackTrace);
    }
    catch (Exception exc)
    {
        try
        {
            MessageBox.Show("Fatal Non-UI Error",
                "Fatal Non-UI Error. Could not write the error to the event log. Reason: "
                + exc.Message, MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }
        finally
        {
            Application.Exit();
        }
    }
}

 

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.Message + "/n/nStack Trace:/n" + e.StackTrace;
    return MessageBox.Show(errorMsg, title, MessageBoxButtons.AbortRetryIgnore,
        MessageBoxIcon.Stop);
}

 


二、B/S 解決方案(以下任何一種方法)
1. 在IE目錄(C:/Program Files/Internet Explorer)下建立iexplore.exe.config文件,內容如下:
<?xml version="1.0"?> 
<configuration>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="true" />
  </runtime> 
</configuration>

 

2. 不建議使用此方法,這將導致使用 framework 1.1 以后版本的程序在IE中報錯。
建立同上的配置文件,但內容如下:
<?xml version="1.0"?> 
<configuration>
  <startup>
    <supportedRuntime version="v1.1.4322"/>
  </startup>
</configuration>

 

3. 這個比較繁瑣,分為三步:
⑴. 將下面的代碼保存成文件,文件名為UnhandledExceptionModule.cs,路徑是C:/Program Files/Microsoft Visual Studio 8/VC/
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Web;
 
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 = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "webengine.dll");

                        if (!File.Exists(webenginePath)) {
                            throw new Exception(String.Format(CultureInfo.InvariantCulture,
                                                              "Failed to locate webengine.dll at '{0}'.  This module requires .NET Framework 2.0.", 
                                                              webenginePath));
                        }

                        FileVersionInfo ver = FileVersionInfo.GetVersionInfo(webenginePath);
                        _sourceName = string.Format(CultureInfo.InvariantCulture, "ASP.NET {0}.{1}.{2}.0",
                                                    ver.FileMajorPart, ver.FileMinorPart, ver.FileBuildPart);

                        if (!EventLog.SourceExists(_sourceName)) {
                            throw new Exception(String.Format(CultureInfo.InvariantCulture,
                                                              "There is no EventLog source named '{0}'. This module requires .NET Framework 2.0.", 
                                                              _sourceName));
                        }
 
                        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
 
                        _initialized = true;
                    }
                }
            }
        }

        public void Dispose() {
        }

        void OnUnhandledException(object o, UnhandledExceptionEventArgs e) {
            // Let this occur one time for each AppDomain.
            if (Interlocked.Exchange(ref _unhandledExceptionCount, 1) != 0)
                return;

            StringBuilder message = new StringBuilder("/r/n/r/nUnhandledException logged by UnhandledExceptionModule.dll:/r/n/r/nappId=");

            string appId = (string) AppDomain.CurrentDomain.GetData(".appId");
            if (appId != null) {
                message.Append(appId);
            }
            
            Exception currentException = null;
            for (currentException = (Exception)e.ExceptionObject; currentException != null; currentException = currentException.InnerException) {
                message.AppendFormat("/r/n/r/ntype={0}/r/n/r/nmessage={1}/r/n/r/nstack=/r/n{2}/r/n/r/n",
                                     currentException.GetType().FullName, 
                                     currentException.Message,
                                     currentException.StackTrace);
            }          

            EventLog Log = new EventLog();
            Log.Source = _sourceName;
            Log.WriteEntry(message.ToString(), EventLogEntryType.Error);
        }
    }
}

 

⑵. 打開Visual Studio 2005的命令提示行窗口 
輸入Type sn.exe -k key.snk后回車
輸入Type csc /t:library /r:system.web.dll,system.dll /keyfile:key.snk UnhandledExceptionModule.cs后回車
輸入gacutil.exe /if UnhandledExceptionModule.dll后回車
輸入ngen install UnhandledExceptionModule.dll后回車 
輸入gacutil /l UnhandledExceptionModule后回車並將顯示的”強名稱”信息復制下來

 

⑶. 打開ASP.net應用程序的Web.config文件,將下面的XML加到里面。注意:不包括”[]”,①可能是添加到<httpModules></httpModules>之間。
<add name="UnhandledExceptionModule" type="WebMonitor.UnhandledExceptionModule, [這里換為上面復制的強名稱信息]" />

 

 

三、微軟並不建議的解決方案
    打開位於 %WINDIR%/Microsoft.NET/Framework/v2.0.50727 目錄下的 Aspnet.config 文件,將屬性 legacyUnhandledExceptionPolicy 的 enabled 設置為 true

 

 

四、跳出三界外——ActiveX
    ActiveX 的特點決定了不可能去更改每個客戶端的設置,采用 B/S 解決方案里的第 3 種方法也不行,至於行不通的原因,我想可能是因為 ActiveX 的子控件產生的異常直接

被 CLR 截獲了,並沒有傳到最外層的 ActiveX 控件,這只是個人猜測,如果有清楚的朋友,還望指正。
   

    最終,我也沒找到在 ActiveX 情況的解決方法,但這卻是我最需要的,無奈之下,重新檢查代碼,發現了其中的問題:在子線程中創建了控件,又將它添加到了主線程的 UI 上。
    以前遇到這種情況,系統就會報錯了,這次居然可以蒙混過關,最搞不懂的是在 framework 2.0 的 C/S 結構下也沒有報錯,偏偏在 IE(ActiveX) 里掛了。唉,都是宿主惹的禍。

 

【轉】CLR20R3 程序終止的幾種解決方案

http://blog.csdn.net/fxfeixue/article/details/4466899

 
http://www.cnblogs.com/zhaozhan/archive/2011/08/22/2150036.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM