简体   繁体   English

AppDomain未处理的异常

[英]AppDomain unhandled exceptions

There are plenty of topics covering the question. 有很多主题涉及这个问题。 But nevertheless I have a problem. 但是我有一个问题。

I load the assembly into new AppDomain like this: 我将程序集加载到新的AppDomain如下所示:

public void Run()
{
    //There's the problem.
    //As Panos Rontogiannis mentioned the thread is created in default AppDomain
    new Thread(RunApp).Start();
}

private void RunApp()
    try
    {
        AppDomain.CreateDomain("domain name").ExecuteAssembly("path to assembly");
    }
    catch (Exception _e)
    {
        MessageBox.Show("Unhandled Exception.\n" + _e);
    }
}

In the Main method of the loaded assembly I subscribe my handler to the UnhandledException event: 在加载程序集的Main方法中,我将处理程序订阅到UnhandledException事件:

AppDomain.CurrentDomain.UnhandledException += handleException;

The handler itself: 处理程序本身:

public static void handleException(object a_s, UnhandledExceptionEventArgs a_args)
{
    var _e = (Exception)a_args.ExceptionObject;
    //Static loger class method
    Loger.WriteError(_e.GetType().ToString(), _e.Message, "default solution");
}

But wherever the exception is thrown in the loaded assembly the handler doesn't get involved. 但是无论何处在加载的程序集中抛出异常,处理程序都不会涉及。 I only catch exception in the default AppDomain (first try{} catch{} ). 我只在默认的AppDomain捕获异常(第一次try{} catch{} )。

Most probably, the reason you cannot handle the exception in the new AppDomain is that it is not thrown from a thread that was created in that AppDomain . 最有可能的是,您无法在新AppDomain处理异常的原因是它不会从该AppDomain中创建的线程抛出。 From the documentation on AppDomain.UnhandledException it is not very straight-forward to see that. AppDomain.UnhandledException上的文档来看,这不是很简单。 The interesting part is the following: 有趣的部分如下:

An exception is unhandled only if the entire stack for the thread has been unwound without finding an applicable exception handler, so the first place the event can be raised is in the application domain where the thread originated. 仅当线程的整个堆栈已展开而未找到适用的异常处理程序时,才会处理异常,因此可以引发事件的第一个位置是发起线程的应用程序域。

Now if the thread that executes the code that throws, is created in your main AppDomain (like the main thread of a console app), then you should add a handler in the main AppDomain . 现在,如果执行抛出代码的线程在主AppDomain创建(如控制台应用程序的主线程),那么您应该在主AppDomain添加一个处理程序。 Note though that if the type of the thrown exception is not loaded in the main AppDomain, the Assembly Loader of .NET will try to load it from your applications' base directory and probing paths. 请注意,如果主AppDomain中未加载抛出异常的类型,.NET的Assembly Loader将尝试从应用程序的基目录和探测路径加载它。 If these are not the same with the child AppDomain , then the assembly will not be resolved and an(other) exception will be thrown. 如果这些与子AppDomain ,则不会解析程序集并抛出(其他)异常。

There are a variety of reasons that this might happen. 这种情况可能有多种原因。 The event documentation at http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx covers quite a bit of this complexity in detail If nothing there seems applicable, could you please post repro code? http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx上的事件文档详细介绍了这种复杂性如果没有什么似乎适用,请你发布repro代码吗?

My guess is the handler is not invoked as the exception is handled. 我的猜测是,处理异常时不会调用处理程序。 ie By the upper try{}catch{}. 即通过上面的try {} catch {}。

I didn't realy understand why the handler doesn't get invoked. 我没有真正理解为什么不调用处理程序。

I ended up using FirstChanceException instead of UnhandledException in Main method of loaded assembly. 我最终在加载程序集的Main方法中使用FirstChanceException而不是UnhandledException。 Like this: 像这样:

AppDomain.CurrentDomain.FirstChanceException +=
    (obj, e) => Loger.WriteError(
        e.Exception.ToString(),
        e.Exception.Message,
        "default solution"
    );

This is a late reply, but this seems to work fine if you ask me (VS2012/.NET 4.5), exception handler needs to be registered before ExecuteAssembly is called of course: (I have a child process that causes an Access Violation by writing to a null ref (unsafe code) just to force a crash and it triggers the HandleException below: 这是一个迟到的回复,但是如果你问我(VS2012 / .NET 4.5)似乎工作正常,在调用ExecuteAssembly之前需要注册异常处理程序:(我有一个子进程通过写入导致访问冲突到一个null ref(不安全的代码)只是为了强制崩溃,它触发下面的HandleException:

public static void HandleException(object a_s, UnhandledExceptionEventArgs a_args)
{
    var _e = (Exception)a_args.ExceptionObject;
    Console.WriteLine(_e.GetType().ToString(), _e.Message, "default solution");
}

public void StarProcessWithinAppDomain(string fileName)
{
    try
    {
        // New appdoamin / check exception isolation level 
        AppDomain sandBox = AppDomain.CreateDomain("sandBox");
        try
        {
            AppDomain.CurrentDomain.UnhandledException += HandleException;
            sandBox.ExecuteAssembly(fileName);
        }
        catch (Exception ex)
        {
            Console.WriteLine("An error occurred (inner) within AppDomain, executing \"{0}\":" + "\n" + ex.Message, fileName);
        }
        finally
        {
            AppDomain.Unload(sandBox); 
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("An error occurred within AppDomain, executing \"{0}\":" + "\n" + ex.Message, fileName);
    }
}
  1. FirstChanceException fires. 触发FirstChanceException
  2. Any catch blocks are executed. 执行任何catch块。
  3. If no catch block or throw in the block then UnhandledException fires 如果没有catch块或throw块,则会触发UnhandledException

Your catch block ensures that UnhandledException doesn't fire. catch块确保UnhandledException不会触发。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM