C# equivalent of DllMain in C (WinAPI)
Give your class a static constructor and do your initialization there. It will run the first time anybody calls a static method or property of your class or constructs an instance of your class.
DLL load notification
Yes, you can get image (.dll, .exe) load events through Windows' ETW (Event Tracing for Windows) facility. ETW is a fast, low-overhead logging mechanism and most of the Windows kernel is instrumented to emit events.
ETW has the concept of a "provider" that emits sets of events. For example, there's a CLR provider for the .NET runtime, a kernel provider for memory manager/driver/image/file system/user events, an IIS provider for HTTP/network events, or even custom providers that 3rd parties write.
You will want to enable EVENT_TRACE_FLAG_IMAGE_LOAD
on the ETW kernel provider in order to get Image_Load
events. For managed code, you can use the AssemblyLoad
or ModuleLoad
events with the CLR ETW provider.
You can produce and consume ETW events from both native and managed code. It's somewhat difficult to work with, but there's a wealth of data available once you start collecting it. Vance Morrison created a short walkthrough on consuming ETW events via C# and created the TraceEvent library.
Also, see my previous SO posts here and here for more on ETW.
Alternatively, you can use WMI (Windows Management Instrumentation) to get these events, although you'll have to poll for them. Polling WMI should still be less resource intensive than constantly enumerating all modules in all processes in the system.
If you go the WMI route, look at the Win32_ModuleLoadTrace
and Win32_Process
types. The .NET framework has a reasonable WMI API.
Where does DLL start when injected?
This code project article gives you a nice walkthrough how to inject .Net assemblies into unmanaged processes. It first loads an unmanaged bootstrapper.dll which does the heavy lifting of loading the .Net runtime and your managed assembly.
C# Class Library How To Add Startup Code
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#".
DllMain calls from C# thread creation/deletion seem to be unbalanced?
Because more threads exited during the lifetime of the DLL than were created during the lifetime of the DLL.
Threads don't remember which DLLs were present when they were created, so you get a detach message for every thread which exits after the DLL was loaded, but you only get attach messages for threads which are created after the DLL was loaded. So if you create n threads, load a DLL, then close those threads, the DLL sees n DLL_THREAD_DETACH
messages but no DLL_THREAD_ATTACH
messages.
It's up to the DLL to decide whether or not to do anything with the detached thread and to remember whether or not it has seen it before; the 'if' is important in 'If the DLL has stored a pointer to allocated memory in a TLS slot, it should use this opportunity to free the memory.' MSDN
Related Topics
Put Wpf Control into a Windows Forms Form
How to Return a Specific Status Code and No Contents from Controller
How to Select Xml Nodes with Xml Namespaces from an Xmldocument
Force JSON.Net to Include Milliseconds When Serializing Datetime (Even If Ms Component Is Zero)
The Calling Thread Must Be Sta, Because Many UI Components Require This in Wpf
Shortcut for "Null If Object Is Null, or Object.Member If Object Is Not Null"
Does Distinct() Method Keep Original Ordering of Sequence Intact
How to Make a Property Protected and Internal in C#
Additional Text Encountered After Finished Reading JSON Content:
Transitive References in .Net Core 1.1
How to Ensure All Data Has Been Physically Written to Disk
Difference Between Char.Isdigit() and Char.Isnumber() in C#
How to Do .Net Binary Serialization of an Object When You Don't Have the Source Code of the Class