Skip to content

Instantly share code, notes, and snippets.

@GrabYourPitchforks
Created January 24, 2020 20:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GrabYourPitchforks/ec80a0d8b75167749f6022bc32ce4234 to your computer and use it in GitHub Desktop.
Save GrabYourPitchforks/ec80a0d8b75167749f6022bc32ce4234 to your computer and use it in GitHub Desktop.
Module initializer sample
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ... -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- This task adds a module initializer to {IL}.txt. -->
<UsingTask TaskName="InjectModuleInitializer" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<Path ParameterType="System.String" Required="true" />
<InitializerMethod ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Text" />
<Code Type="Fragment" Language="cs"><![CDATA[
StringBuilder sb = new StringBuilder();
string s = File.ReadAllText(Path, Encoding.UTF8);
sb.Append(s);
sb.AppendLine();
sb.AppendLine(@"// Module initializer");
sb.AppendLine(@".method private specialname rtspecialname static void .cctor() cil managed {");
sb.AppendLine(@".maxstack 0");
sb.Append(@"call void ");
sb.Append(InitializerMethod);
sb.AppendLine(@"()");
sb.AppendLine(@"ret");
sb.AppendLine(@"} // end of global method .cctor");
File.WriteAllText(Path, sb.ToString(), Encoding.UTF8);
]]></Code>
</Task>
</UsingTask>
<PropertyGroup>
<!-- by default, we're not optimized -->
<IlasmDebugMode>impl</IlasmDebugMode>
<!-- if build optimization is enabled, pass the OPT parameter to ilasm -->
<IlasmDebugMode Condition="'$(Optimize)' == 'true'">opt</IlasmDebugMode>
<IntermediateIlFile>$(IntermediateOutputPath)$(TargetName).il</IntermediateIlFile>
<IntermediateResourceFile>$(IntermediateOutputPath)$(TargetName).res</IntermediateResourceFile>
</PropertyGroup>
<Target Name="AfterCompile" Inputs="@(IntermediateAssembly)" Outputs="$(IntermediateIlFile)">
<!--Disassemble the DLL, inject the module initializer, then reassemble-->
<Delete Files="$(IntermediateIlFile)" />
<Exec Command="&quot;$(SDK40ToolsPath)ildasm.exe&quot; /nobar /linenum /utf8 /typelist /out=&quot;$(IntermediateIlFile)&quot; &quot;@(IntermediateAssembly)&quot;" WorkingDirectory="$(MSBuildProjectDirectory)" />
<!-- Create a static method somewhere with the following signature:
internal static void Initialize() { /* ... */ }
Then update "InitializerMethod" below to have the value "{namespace}.{typename}::{initializer_method_name}".
The sample below is what the Microsoft.Web.Infrastructure assembly uses. -->
<InjectModuleInitializer Path="$(IntermediateIlFile)" InitializerMethod="Microsoft.Web.Infrastructure.ModuleInitializer::Initialize" />
<Exec Command="&quot;$(MSBuildToolsPath)\ilasm.exe&quot; /nologo /quiet /dll /debug=$(IlasmDebugMode) /resource=&quot;$(IntermediateResourceFile)&quot; /output=&quot;@(IntermediateAssembly)&quot; &quot;$(IntermediateIlFile)&quot;" WorkingDirectory="$(MSBuildProjectDirectory)" />
<!--Absolutely necessary the touch the IL file so that this target gets correctly skipped in incremental builds-->
<Touch Files="$(IntermediateIlFile)" />
</Target>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment