8

What is the underlying implementation of GetEntryAssembly in C#? And why it does return null when dll was loaded from an unmanaged application?

The MSDN documentation says:

The GetEntryAssembly method can return null 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 have the following setup:

Native executable (C++) -> Mixed mode assembly (C++/cli) -> Managed assembly (C#)

Managed assembly is optional, in mixed mode assembly one can call GetEntryAssembly and get null.

While debugging we've tracked to this call in C# source code:

[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
private static extern void GetEntryAssembly(ObjectHandleOnStack retAssembly);

We can see that the entry assembly should be the native executable. However it is not retrieved. I wonder what are the reasons for this? Shouldn't native to managed transition take care of that?

Edit

GetEntryAssembly is used internally by .NET. We are just experiencing the side effect when it returns null. Reproducible with one line in Managed assembly:

System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain ();

This will throw the following exception: System.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain. The root cause for this exception seems to be the entry assembly being null.

Robertas
  • 1,164
  • 3
  • 11
  • 26
  • 3
    It is implemented in the CLR. Same case of course, it cannot return an Assembly object reference, your native C++ executable is not an assembly. Consider using Process.GetCurrentProcess() instead. – Hans Passant Oct 24 '16 at 11:35
  • I'm not using GetEntryAssembly directly in my code. This is used internally by C#. And since it returns null, some other code down the line misbehaves. E.g. if one calls `System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain` will get a `System.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain.` – Robertas Oct 24 '16 at 11:50
  • You'll of course have to fix the "other code down the line", it cannot rely on isolated storage working. No point in hiding this info from your question btw, it does not help us help you. – Hans Passant Oct 24 '16 at 12:13
  • I wanted to make it a general question, sorry. To provide a full picture we are using Open XML SDK, which for large files starts using IsolatedStorage instead of the main memory. And failes to perform operation due to aforementioned exception. Hence the question about entry assemby. – Robertas Oct 24 '16 at 12:23
  • Possible duplicate of [I need an alternative to \`Assembly.GetEntryAssembly()\` that never returns null](http://stackoverflow.com/questions/14165785/i-need-an-alternative-to-assembly-getentryassembly-that-never-returns-null) – Michael Freidgeim Apr 13 '17 at 08:28
  • I was in the same situation that it required me to call C# objects from native C++. I got null when calling GetEntryAssembly. But instead I called Assembly.GetAssembly, and this worked for me. – Louis Apr 06 '20 at 13:11

2 Answers2

17

In my case, GetEntryAssembly() returned null when called by a unit test framework. For me, it was sufficient to switch to GetCallingAssembly(). Probably won't work in every situation, but for some it will.

A C# example (from Olivier's comment):

var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();

An F# example:

let getEntryAssembly() =
    match Assembly.GetEntryAssembly() with
    | null -> Assembly.GetCallingAssembly()
    | entryAsm -> entryAsm
Wallace Kelly
  • 15,565
  • 8
  • 50
  • 71
4

Assembly is .NET specific class. As you mentioned you call managed methods from unmanaged code, and GetEntryAssembly will return null because there is no reason to return anything at all!

All methods in assembly bound to .NET architecture, and there is no possible implementation for C++, Java or any other external compiled source.

If you still don't get it - try to imagine using reflection with this kind of 'Assembly': getting some hard-core optimized c++ names of methods, or getting types of variables...and this is only for C++, not to mention other languages.

Yennefer
  • 5,704
  • 7
  • 31
  • 44
eocron
  • 6,885
  • 1
  • 21
  • 50
  • `GetEntryAssembly` is called inside .NET implementation. Which down the line fails with the exception because `GetEntryAssembly` returned null previously. It seems that not all of the `Native -> Mixed mode -> Managed` workflows are supported by .NET. – Robertas Oct 24 '16 at 12:02