3

Below is how to write C++ functionality to do something when the DLL is first called on the server. How does one do this in C# Class Library? The Startup in properties is grayed (disabled) for Class Library project out in Visual Studio but need to be library as I'm using it in my web application as reference. And not sure how to write an equivalent in C# so I could do some code to log events when the dll is loaded or started.

BOOL WINAPI DllMain(
  HINSTANCE hinstDLL, // handle to DLL module
   DWORD fdwReason, // reason for calling function
   LPVOID lpReserved ) // reserved
{
   // Perform actions based on the reason for calling.
   switch( fdwReason )
   {
     case DLL_PROCESS_ATTACH:
        // Initialize once for each new process.
        // Here is where the module POST should be invoked
        // Return FALSE to fail DLL load in case POST fails
     break;
     case DLL_THREAD_ATTACH:
        // Do thread-specific initialization.
     break;
     case DLL_THREAD_DETACH:
     // Do thread-specific cleanup.
     break;
     case DLL_PROCESS_DETACH:
     // Perform any necessary cleanup.
     break;
     }
     return TRUE; // Successful DLL_PROCESS_ATTACH.
}
Andrey Korneyev
  • 26,353
  • 15
  • 70
  • 71
moto_geek
  • 510
  • 5
  • 14
  • *as I'm using it in my web application as reference* If it's hosted in IIS use that pre-application start attribute. http://dailydotnettips.com/2011/08/27/initialize-assemblies-using-preapplicationstartmethodattribute-aspnet4-app/ – ta.speot.is Dec 18 '14 at 13:58
  • Possible [C# equivalent of DllMain in C (WinAPI)](http://stackoverflow.com/questions/8206736/c-sharp-equivalent-of-dllmain-in-c-winapi)? – Andre Hofmeister Dec 18 '14 at 14:10
  • *"The Startup in properties is grayed (disabled) for Class Library project out in Visual Studio but need to be library as I'm using it in my web application as reference."* -- You can reference executable assemblies from other projects just like you can reference class libraries. – rory.ap Dec 18 '14 at 14:21

3 Answers3

3

I'm using it in my web application as reference

If it's hosted in IIS you can use PreApplicationStartMethodAttribute to run code very early on in your application startup.

This allows you to perform once-off initialisation but might force the initialisation earlier than necessary, because IIS will run your code as the application starts up rather than the first time you use classes in the assembly.

how to write an equivalent in C# so I could do some code to log events when the dll is loaded or started.

DllMain has some pretty severe restrictions. You can't expect to be able to log events reliably from DllMain anyway, so there's no precedent for "I can do it like this in C++ now how do I do it in C#".

ta.speot.is
  • 26,914
  • 8
  • 68
  • 96
  • Logging can be safe: "The following tasks are safe to perform within `DllMain` - Open, read from, and write to files." as long as you don't do it from C#: "You should never perform the following tasks from within `DllMain` - Use managed code" - http://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx#general_best_practices – MSalters Dec 18 '14 at 15:59
1

There is no such construct in C#. C# is an object-oriented language, so all* executable code resides in classes. The CLR supports such an initialization, but it is not available in C# or VB.NET.

ASP.NET does support attributes that can be added to assemblies to execute code on startup, but it's specific to ASP.NET; it does not get executed when you load the assembly into a WPF app, for example.

However, that also means that you do not need library initialization code in C#. If you have code that needs to be run before classes in the assembly are used, then use the static or instance constructors of those classes to initialize appropriately.

If you have expensive code that is not appropriate to run in a constructor, my next choice would be a documented Init method where you allow the user to choose when to run initialize code. If the user chooses not to run it at startup (or does not know to, then run it when the initialization is required (constructor, member access, etc.)

* I would expect that are some esoteric exceptions, but none that I can think of

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • 1
    One exception: when you have to pre-cache values or objects and operation is pretty expansive. if it can be started during startup then when user will trigger an action that will read that values...he won't wait. Of course you can put some initialization code in your Main() but...it would be better to avoid. – Adriano Repetti Dec 18 '14 at 14:05
  • Initializers for global objects live outside classes. That's not very esoteric, is it? And isn't that precisely how C# uses that CLR initialization you mentioned in the first paragraph? – MSalters Dec 18 '14 at 16:02
0

I'm not sure if this is the best approach, but you could use a static constructor, for example:

public static class Class1
{
    static Class1()
    {
       //this constructor will be called the first time this class is used.
    }
}

Note, that this constructor would not be called until the first time any of the static members of the DLL are used, which is why this may not be the best approach. However, you could, of course, take care of any instance-based initiation in an instance constructor.

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • 1
    It will be called when first static member is accessed, not when DLL is loaded. If you access Class1 after 2 hours...it'll be called after 2 hours. If you won't ever call any member it won't be called at all. DllMain is called when DLL is loaded... – Adriano Repetti Dec 18 '14 at 13:56
  • @AdrianoRepetti -- referenced assemblies are loaded as needed, not when the application first starts. So if the first time it's needed is when the static member is used -- be it right away or after two hours -- then that's when the static constructor will run. But you did point out one thing: it will only run when static members are referenced. – rory.ap Dec 18 '14 at 14:01
  • unless explicitly loaded but we don't know more about OP scenario anyway core of my thought is just: [in C#] you do not have any even for when DLL is loaded, caller should trigger your code somehow. – Adriano Repetti Dec 18 '14 at 14:11