Net4x.InjectModuleInitializer
1.3.0.26250
dotnet add package Net4x.InjectModuleInitializer --version 1.3.0.26250
NuGet\Install-Package Net4x.InjectModuleInitializer -Version 1.3.0.26250
<PackageReference Include="Net4x.InjectModuleInitializer" Version="1.3.0.26250"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Net4x.InjectModuleInitializer" Version="1.3.0.26250" />
<PackageReference Include="Net4x.InjectModuleInitializer"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Net4x.InjectModuleInitializer --version 1.3.0.26250
#r "nuget: Net4x.InjectModuleInitializer, 1.3.0.26250"
#:package Net4x.InjectModuleInitializer@1.3.0.26250
#addin nuget:?package=Net4x.InjectModuleInitializer&version=1.3.0.26250
#tool nuget:?package=Net4x.InjectModuleInitializer&version=1.3.0.26250
Net4x.InjectModuleInitializer
Runs a method of your choosing once, automatically, before anything else in your assembly is touched — the CLR's module initializer.
C# has no syntax for one on the frameworks this package targets ([ModuleInitializer] arrived in C# 9 and
only works on .NET 5+). The CLI does support it, though: every module may carry a <Module>::.cctor, and
the runtime guarantees it runs exactly once, before the first access to any type in that module. This
package adds that method to your compiled assembly after the build, so the feature is available all the way
back to .NET Framework 3.5.
It is a build-time tool. Nothing from this package ends up as a dependency of your assembly.
Getting started
Install the package:
dotnet add package Net4x.InjectModuleInitializer
Add a class named ModuleInitializer with a method named Run anywhere in the project:
internal static class ModuleInitializer
{
internal static void Run()
{
// Runs once, before any type in this assembly is first used.
}
}
Build. That is the whole setup — the package brings an MSBuild targets file that runs after every successful build and rewrites the output assembly in place.
The method it looks for
By default the tool looks for a type called ModuleInitializer in any namespace and a method on it
called Run. The method must be:
| Requirement | Why |
|---|---|
public or internal |
private and protected are not callable from <Module>::.cctor |
static |
there is no instance to call it on |
void |
the module constructor has nowhere to put a return value |
| no parameters | the runtime calls it with no arguments |
Break one of those and the build fails with a message naming the rule.
What it does to your assembly
Given ModuleInitializer.Run, the tool adds this to the module:
.method private static specialname rtspecialname void .cctor() cil managed
{
call void ModuleInitializer::Run()
ret
}
Debug symbols are read and rewritten alongside the assembly, so stepping through the build output still works. Portable, embedded and classic Windows PDBs are all preserved.
Command line
The MSBuild targets call the tool for you. If you want to run it yourself — over an assembly you did not
build, say — it is under tools/ in the package:
InjectModuleInitializer.exe [/m:<method>] [/k:<keyfile>] <assembly>
| Option | Meaning |
|---|---|
/m:, /moduleinitializer: |
Use a specific method instead of the ModuleInitializer.Run convention, written Full.Type.Name::MethodName — e.g. /m:My.Startup.Bootstrap::Initialize. The type name is the full name including namespace; the separator is two colons. |
/k:, /keyfile: |
Re-sign the assembly with this strong name key after injecting. Needed whenever the assembly was signed, because rewriting it invalidates the existing signature. |
/?, /h, /help |
Print usage. |
Exit code is 0 on success and 1 on any failure, with the reason on standard error.
Strong-named assemblies
If your project sets SignAssembly and AssemblyOriginatorKeyFile, the targets file passes the key
through automatically — there is nothing to configure. Signing is a .NET Framework capability, so it works
when the tool runs on .NET Framework, which is the case for every assembly the MSBuild integration
selects.
What is in the package
build/
Net4x.InjectModuleInitializer.props sets InjectModuleInitializerTool for your target framework
Net4x.InjectModuleInitializer.targets the AfterBuild target that runs it
tools/
net35/ net40/ net45/ netstandard2.0/ the tool, with Mono.Cecil alongside it
The props file picks the tool by the framework your project targets: net35 for net35, net40 for
net40, and the net45 build for everything else. That build is a .NET Framework executable, so the
MSBuild integration expects a Windows build host with .NET Framework available.
The InjectModuleInitializer target is incremental — it is skipped when the assembly has not been rebuilt
— and registers its stamp file for Clean.
Credits
Originally written by Einar Egilsson; this
package repackages it for the Net4x set. Assembly rewriting is done with
Mono.Cecil.
MIT licensed.
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.3.0.26250 | 104 | 9/7/2026 |
| 1.1.0 | 578 | 8/27/2023 |