Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw exception from AppDomain.AssemblyLoad event

Tags:

c#

.net

exception

Can someone explain to me why I cannot seem to throw an exception from inside the AppDomain.Assembly load event? For example:

class Program
{
    static Program()
    {
        AppDomain.CurrentDomain.UnhandledException += (s, a) =>
        {
            Console.WriteLine("Caught exception!");
        };

        AppDomain.CurrentDomain.AssemblyLoad += (s, a) =>
        {
            Console.WriteLine(string.Format("Assembly {0} loaded", a.LoadedAssembly.FullName));

            throw new Exception();

            Console.WriteLine("Should never get here...");
        };
    }

    static void Main(string[] args)
    {
        Console.WriteLine(new ClassLibrary1.Class1().TestString());
        Console.WriteLine();
        Console.WriteLine("Done...");
        Console.ReadLine();
    }
}

When I execute this, the output is as follows:

Assembly ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null loaded
TestString
Done...

Can anyone explain this behavior to me? Thank you.

EDIT To clarify a couple things:

  • The assembly load event runs fine, when I expect it to run. But my exception never gets thrown

  • This is a distilled example taken from a larger application. I want to inspect the assembly after it is loaded and if I don't like something about it, I want to fail fast... But my exception doesn't 'happen'

like image 980
TheNextman Avatar asked Feb 10 '11 13:02

TheNextman


2 Answers

This happens because of the way the JIT compiler works. It needs to generate the code for the Main() method before it can start to run. Since you are referencing the ClassLibrary1.Class1() type, it needs to load that assembly to retrieve type info. That requires it to load the assembly before your code starts running. Change it like this to get the exception:

using System.Runtime.CompilerServices;
...
    static void Main(string[] args) {
        Test();
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    static void Test() {
        Console.WriteLine(new ClassLibrary1.Class1().TestString());
        Console.WriteLine();
        Console.WriteLine("Done...");
        Console.ReadLine();
    }

Now the static constructor can run first and register the AssemblyLoad event handler before the ClassLibrary1 assembly gets loaded.

like image 174
Hans Passant Avatar answered Oct 23 '22 12:10

Hans Passant


Why do you think the exception is not being thrown? If it weren't being thrown, one would expected to see your "Should never get here..." output. However, since it's not there, the exception presumably is being thrown.

Your code not catching the exception is a whole other story. It's quite possible that the code that raises the AppDomain.AssemblyLoad event is catching exceptions.

like image 1
Nicole Calinoiu Avatar answered Oct 23 '22 13:10

Nicole Calinoiu