I am using pinvoke from a .NET (C#) dll to call into a native dll. Now I would like to compile my .NET dll as "AnyCPU" but when "pinvoking", I must know, whether I have to call into the 32 or 64 bit dll. I install both versions of the native dlls into the subfolder bin32 and bin64. Now when my DLL gets loaded, I would like to check, whether we are in 32 or 64 bit mode and call SetDllDirectory with the appropriate path. There seems to be no problem with this approach, except for a good "entrypoint" from where to call SetDllDirectory. In native DLLs there is a DllMain entry, which gets called, when the DLL is attached to a process. Is there some similar entrypoint in a .NET DLL? Do you think, dynamically calling SetDllDirectory is a good idea?
2 Answers
.NET does have the equivalent of a DllMain() function, it is called a module initializer. It is however out of reach from C# and VB.NET code, you can only create one in IL or in C++/CLI. C++/CLI itself has a bitness dependency so that only leaves IL. You'll find sample code for one in this answer. Getting it linked into your assembly is pretty awkward, the build system doesn't directly support running the assembly linker.
Next best thing is a "type initializer" as mentioned in the same article, called a static constructor in C#. You do need some semblance of organization in your code to make these pay off, a class that's guaranteed to get used before one of your 'thousands of methods' get called. That ought to be difficult with that many methods.
That doesn't leave much beyond an initialization method that has to be called by the app in its Main() method. And of course the standard solution, two installers, one for 32-bit machines, another for 64-bit machines. Which also ensures your app ends up in the 'right' directory, c:\program files vs c:\program files (x86).
UPDATE: .NET 5 now supports module initializers in C# v9 with the [ModuleInitializer] attribute

- 922,412
- 146
- 1,693
- 2,536
-
I think this suould be good solution for you http://msdn.microsoft.com/en-us/library/windows/desktop/ff951640%28v=vs.85%29.aspx at least on Windows. I had to do some magic with registry with my problem so I used Module Initilazer aprocah. This also can be avoided if you wrap your managed object creation in factory like class where you are going to do your initalization or try put it in your static class(constructor) where you keep your pinvoke definitions. – user629926 Mar 04 '13 at 14:23
Essentially what you are asking is whether or not you can write code that will be executed when an assembly is first loaded. That question is addressed here: .Net: Running code when assembly is loaded
In your position I would put the onus on the user of your library. Provide a function that initializes your library, and ask the user of the library to call it before any other function.
You could, if you wished, take that initialization inside your library using lazy initialization. So, all of your methods could look like this:
private static void EnsureInitialized()
{
if (!MyLibraryInitialized)
InitializeMyLibrary();
}
public static void DoSomething()
{
EnsureInitialized();
.... // implementation of DoSomething
}
I would also recommend against using SetDllDirectory
. There's an easier way to do it. Since you can get hold of the full path to the DLL that needs to be loaded, simply load it in InitializeMyLibrary()
with a call to LoadLibrary()
. Once the DLL is loaded, your p/invokes will automatically be bound to the DLL that you already loaded.

- 1
- 1

- 601,492
- 42
- 1,072
- 1,490
-
Thanks, LoadLibrary is certainly better than SetDllDirectory in many circunstances, but unfortunatly not in my situation, where there are dozens of DLLs which might get loaded, depending on what methos the user is calling. I don't want to consume this memory space, if it will not be needed. – Gerhard Mar 04 '13 at 12:35
-
1@Gerhard I'm not proposing loading them all on startup. Just loading what is needed. However, if these DLLs have dependencies on each other, then you need to modify the DLL search path so that dependencies are resolved appropriately. – David Heffernan Mar 04 '13 at 12:38
-
Your answer doesn't definitely state that there is no "DllMain" in managed DLLs, you provide a good workaround. Unfortunately there are thousands of methods in my DLL, so I cannot use the "Initialized" precheck. I will check your answer as accepted answer, if noone comes up with a DllMain in managed code. Thanks again. – Gerhard Mar 04 '13 at 12:39
-
If you can't use lazy initialization then you can ask the user to call your initialization function. However, I don't believe that you really do have thousands of pinvoke calls in your library. – David Heffernan Mar 04 '13 at 12:47