NativeDllMain 1.0.0
dotnet add package NativeDllMain --version 1.0.0
NuGet\Install-Package NativeDllMain -Version 1.0.0
<PackageReference Include="NativeDllMain" Version="1.0.0" />
<PackageVersion Include="NativeDllMain" Version="1.0.0" />
<PackageReference Include="NativeDllMain" />
paket add NativeDllMain --version 1.0.0
#r "nuget: NativeDllMain, 1.0.0"
#:package NativeDllMain@1.0.0
#addin nuget:?package=NativeDllMain&version=1.0.0
#tool nuget:?package=NativeDllMain&version=1.0.0
NativeDllMain 
A static library for NativeAOT projects, providing a native DllMain implementation that safely invokes a managed entrypoint after the Windows loader lock is released.
This library is necessary because the dotnet runtime initialization code does not meet the restrictions imposed by the Windows loader lock, making it impossible to implement DllMain directly in managed code.
NOTE: This functionality is only enabled when targeting win-x64 or win-x86.
Usage
- Reference the NativeDllMain NuGet package in your project.
- Add the following method to your project:
[UnmanagedCallersOnly(EntryPoint = "DllProcessAttach")]
public static void Main(nint hModule) // can be named anything you want as long as the unmanaged symbol is set to be "DllProcessAttach"
{
/*
Your entrypoint code here
*/
}
Now, when your DLL is loaded, CreateThread is used to spawn a new thread for your managed entrypoint, which will be suspended until after the loader lock is released.
QueueUserAPC
If an application queues an APC before the thread begins running, the thread begins by calling the APC function.
For a DLL that is loaded via the Import Address Table (IAT), such as a proxy DLL, DllMain is called before the main thread begins execution. Therefore it's recommended to use QueueUserAPC to call your managed entrypoint, instead of CreateThread, which prevents a race condition between the main thread and your managed entrypoint.
To enable this behaviour, add the following to a <PropertyGroup> in your csproj:
<DllMainUseQueueUserApc>true</DllMainUseQueueUserApc>
NOTE: If your DLL is loaded via LoadLibrary or similar, you should continue to use CreateThread (the default behaviour), otherwise your managed entrypoint may never be called.
Building
Essentially just replicate the CI instructions.
License
This project is subject to the terms of the Mozilla Public License, v. 2.0.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 218 | 11/8/2025 |