Awhile ago I wrote about how I used msbuild tasks to support obfuscating a project before generating a publish manifest and publishing a project using ClickOnce. It had some limitations but it has served me well for a long time.
I recently upgraded to VS 2010 and found that the old targets didn’t work. Some of the tasks I used already existed in the common targets so I had to copy and modify them. They’ve changed the contents of some of these tasks and that broke the manifest signing.
But also introduced in VS 2010 is the NuGet package management system, and I’ve found myself using more libraries from open source projects that I don’t want to merge into my main assembly and obfuscate. I also had several COM interop libraries that were also being merged, and although they were small this was still an annoyance.
This problem of exclusions is a lot easier than before. In VS 2010, Microsoft introduced Inline Tasks which allow you to embed arbitrary C# or VB.NET code and have that run as a task. (Before you had to create a special arcane dll and register and manage its location so this is a huge step forward.)
So I updated my targets file with a task that filters out known exclusions (NuGet, COM interop, and framework libraries) as well as processing a comma-separated list of wildcard-based exclusions.
Here’s the new targets file that should be placed in the same directory as the project you want to publish.
Add settings and a reference to the targets file at the end of your project file between the highlighted lines.
<Project> ... <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> <!-- Use the following settings to control how and if the output is obfuscated. --> <Target Name="BeforeBuild" Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <CreateProperty Value="true"> <Output TaskParameter="Value" PropertyName="Obfuscate" /> </CreateProperty> <CreateProperty Value="-compression 0 -obfuscation 1 -obfuscate_public_types 1 -exclude_enums 1 -antitamp 1 -suppressildasm 1 -necrobit_comp 1 -mapping_file 1 -resourceencryption 1 -stringencryption 1"> <Output TaskParameter="Value" PropertyName="ObfuscatorOptionsOverride" /> </CreateProperty> <CreateProperty Value="true"> <Output TaskParameter="Value" PropertyName="ShouldMergeAssemblies" /> </CreateProperty> <CreateProperty Value="Irony.*"> <Output TaskParameter="Value" PropertyName="MergeExclusions" /> </CreateProperty> </Target> <Import Project="$(MSBuildProjectDirectory)\Obfuscation2010.targets" /> </Project>
As you can see, we use it in the same manner as the old version except for the new
MergeExclusions setting and the removal of
MergeAssembliesArgOverride. In this example, I’m using the excellent .NET language definition and parsing library called Irony. The filter “Irony.*” will exclude both “Irony.dll” and “Irony.Interpreter.dll”. I could have also excluded them by putting them in a comma-separated list like so: “Irony.dll,Irony.Interpreter.dll”