Search code examples
c#.netassembliesentry-pointstatic-constructor

What is the earliest entrypoint that the CLR calls before calling any method in an assembly?


In the past years I've occasionally been wondering what equivalent of the (in)famous DLL_PROCESS_ATTACH was available in the .NET world. Any documentation I have says, slightly simplified, that the earliest entry point to a class is the static constructor (cctor), but you cannot influence when it is called, nor can you define one cctor that's guaranteed to be called prior to any other cctor or field initializer, hack, it may not even be called at all if the class is never used.

So, if you want to guarantee something's initialized before any method of your assembly is called and you don't want to have to add a cctor to every class in your assembly, what approach can you take? Or is there an easy, managed solution in .NET that I have missed all these years?


Solution

  • I'd normally not answer my own question, but meanwhile I did find an answer that hasn't come up here before, so here I go.

    After some research, I happened on this post by Microsoft, which explains the problems of mixing managed and unmanaged code inside DllMain and the solution, which came about with the 2nd version of the CLI, module initializers. Quote:

    This initializer runs just after the native DllMain (in other words, outside of loader lock) but before any managed code is run or managed data is accessed from that module. The semantics of the module .cctor are very similar to those of class .cctors and are defined in the ECMA C# and Common Language Infrastructure Standards.

    While I wasn't able to find the term module initializer inside the current ECMA specification, it follows logically from type initializer and the global <Module> special class (see section 22.26 on MethodDef, sub-point 40). This feature was implemented after .NET 1.1 (i.e., from 2.0 onwards). See also this semi-official description.

    This question wasn't about C#, but because it is the lingua franca of .NET: C# doesn't know global methods, and you can't create a <Module>, let alone its cctor. However, Einar Egilsson has recognized this apparent deficiency and created InjectModuleInitializer.exe that allows you to do this as a post/compile step from Visual Studio. In C++.NET, using this method is trivial and recommended practice in place of DllMain. See also this SO answer by Ben Voigt (not the accepted answer) and this SO answer by yoyoyoyosef.

    In short, the module initializer is the first method that is called after loading the module (not necessarily when loading assembly!) and before calling any class or instance method. It takes no parameters, returns no value, but can contain any managed code in its body.