Assembly NullReferenceException & .NET Reflector

on Monday, April 20, 2009

Problem

I was receiving a NullReferenceException when running a third party dll through NUnit. Which made it difficult to debug, because I couldn’t step through/alter the third party dll’s source code.

Analysis

Thankfully the stack trace showed the class, method, and line number of the error. I was able to look through the third party dll using Reflector, and found this line:

builder.AppendLine(Assembly.GetEntryAssembly().Location);

It seemed pretty straight forward that the GetEntryAssembly() method call was returning a null value. But, why?

The explanation came from the remarks section (among other places on the page) of the MSDN documentation:

The GetEntryAssembly method can return null (Nothing in Visual Basic) when a managed assembly has been loaded from an unmanaged application. For example, if an unmanaged application creates an instance of a COM component written in C#, a call to the GetEntryAssembly method from the C# component returns null, because the entry point for the process was unmanaged code rather than a managed assembly.

I had always thought that NUnit was managed code, but maybe there was an intermediate level of unmanaged code which was executing NUnit. This seemed probable because NUnit was being called from NAnt which was being called from CruiseControl.Net. And, the error was not happening when I was ran NUnit through ReSharper within Visual Studio.

I just needed a way to update the third party source code to remove/rewrite the offending line.

Solution

Reflector has a FileDisassembler addin which can take the decompiled output and write it to disk. It can even take an entire dll and create a Visual Studio project when exporting the code.

The decompiled output for this assembly had a few compile errors, but started working after a few redundant “compile-fix-error” steps in Visual Studio.

Once the solution was updated to use the decompiled code, I added in a static method which replaced all calls to Assembly.GetEntryAssembly() within the project:

using System.Reflection;
 
namespace Some.Namespace
{
    /// <summary>
    /// This class handles retrieving assemblies which have the potential of returning null values.
    /// </summary>
    public static class AssemblyHandler
    {
 
        /// <summary>
        /// Retrieves the entry assembly when available. If it is not available then the calling
        /// assembly is returned.
        /// </summary>
        /// <returns>The highest level executing assembly which can be found within executing AppDomain.</returns>
        public static Assembly GetEntryAssembly() {
            Assembly    asm    = Assembly.GetEntryAssembly();
            if( asm == null )    asm    = Assembly.GetCallingAssembly();
            return asm;
        }
 
    }
}


After a new compile, the NullReferenceException disappeared.



2 comments:

DeveloperDame said...

I don't believe this is the reason that null is returned.

I believe the reason is because nunit is run in a different AppDomain and so GetEntryAssembly is null. Nunit is managed code as far as I know.

Your solution is exactly what I've done thought :)

Anonymous said...

http://frostwave.googlecode.com/svn-history/r75/trunk/F2DUnitTests/Code/AssemblyUtilities.cs

Post a Comment


Creative Commons License
This site uses Alex Gorbatchev's SyntaxHighlighter, and hosted by herdingcode.com's Jon Galloway.