MSBuild
MSBuild is the build system used by Visual Studio, Visual Studio for Mac, and the .NET Core SDK (dotnet
).
It can also be invoked from the command line.
You can integrate Dotfuscator into your .NET projects using Dotfuscator's MSBuild targets.
Dotfuscator also provides MSBuild tasks that can be called from your own custom build targets.
This page gives a functional overview of these components and explains best practices for using them. For a complete technical reference, see the MSBuild Reference page.
Locating the MSBuild Components
Dotfuscator's MSBuild components can be found in the following directories, based on the installation package you used:
Installation Package | Directory |
---|---|
Windows Installer | $(MSBuildProgramFiles32)\MSBuild\PreEmptive\Dotfuscator\7 |
NuGet Package | {install dir}/tools/msbuilddir |
where:
$(MSBuildProgramFiles32)
is a reserved MSBuild property pointing to theC:\Program Files (x86)
directory on 64-bit versions of Windows andC:\Program Files
on 32-bit versions.{install dir}
is the Dotfuscator installation directory you noted when installing the NuGet package.
Handling Multiple Environments
Because the MSBuild components directory can differ depending on how Dotfuscator was installed, we recommend using an MSBuild property when importing the targets or tasks into your project file.
This User Guide uses a property named DotfuscatorMSBuildDir
, defined in a project file like so:
<!-- Import environment-specific properties, which may include DotfuscatorMSBuildDir -->
<Import Project="$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.dotfuscator.user.props"
Condition="Exists('$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.dotfuscator.user.props')"/>
<!-- Set a default value for the DotfuscatorMSBuildDir property -->
<PropertyGroup>
<DotfuscatorMSBuildDir Condition="'$(DotfuscatorMSBuildDir)' == ''">$(MSBuildProgramFiles32)/MSBuild/PreEmptive/Dotfuscator/7</DotfuscatorMSBuildDir>
</PropertyGroup>
On machines where Dotfuscator is installed using the Windows Installer, you do not need to set DotfuscatorMSBuildDir
anywhere else.
The default value specified in the project file will point to the correct directory.
On machines where Dotfuscator is installed using the NuGet package, you will need to set the DotfuscatorMSBuildDir
property to the NuGet {install dir}
.
Ways to do this include:
Setting the property in the
.dotfuscator.user.props
file.Setting a
DotfuscatorMSBuildDir
environment variable (as all environment variables are exposed as MSBuild properties).Setting the property in a
Directory.Build.props
orDirectory.Build.targets
file located in an ancestor directory of your project's directory.When calling the
msbuild
ordotnet
command lines, specifying the property as an argument.
Once this property is set as needed, your project can import the targets or use the tasks, specifying $(DotfuscatorMSBuildDir)
as the directory.
The .dotfuscator.user.props file
A convenient way to set user-specific MSBuild properties, such as the aforementioned DotfuscatorMSBuildDir
, is to create an MSBuild .props
file in a well-known directory and have your projects import that file.
The project will have the same content across environments, but the .props
file will differ.
This .props
file can have any path you want, but for consistency with the examples in this User Guide we recommend creating a .dotfuscator.user.props
file in your user directory.
(Your user directory is given by an environment variable: USERPROFILE
on Windows, HOME
on macOS and Linux.)
Here's an example of such a file:
<!-- This is an MSBuild properties file for projects which use Dotfuscator's MSBuild components.
For details, see <https://www.preemptive.com/dotfuscator/pro/userguide/en/interfaces_msbuild.html#user>.
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- Path where Dotfuscator's MSBuild components are installed. -->
<DotfuscatorMSBuildDir>C:\apps\Dotfuscator\tools\msbuilddir</DotfuscatorMSBuildDir>
<!-- License string for Dotfuscator. -->
<DotfuscatorLicense>00000000000000000000000000000000</DotfuscatorLicense>
</PropertyGroup>
</Project>
This example sets two environment-specific properties:
DotfuscatorMSBuildDir
is set to a custom directory where Dotfuscator was installed via the NuGet package.If you install via the Windows Installer, then you don't need to set this property.
DotfuscatorLicense
is set to a license key formatted as a license string. This will cause Dotfuscator to automatically activate itself when the MSBuild targets run. If you call theDotfuscate
task manually, you can get the same effect by passing this property to the task'sLicense
input parameter.If you activated Dotfuscator with the Windows Installer, Config Editor, or environment variable, then you don't need to set this property.
The .dotfuscator.user.props
file can be removed entirely if you have no properties to set.
To import the .dotfuscator.user.props
file from a user directory into your project, add the following lines to your project file (.csproj
, .vbproj
, etc.) if not already present:
<Import Project="$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.dotfuscator.user.props"
Condition="Exists('$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.dotfuscator.user.props')"/>
Make sure to place these lines earlier in the project file than any uses of the properties it can set.
MSBuild Targets
Dotfuscator provides MSBuild targets that can be imported into Visual Studio projects to automatically apply protection during builds. The advantages of using these MSBuild targets include:
Dotfuscator applies its protection as part of your normal build process in Visual Studio and MSBuild, instead of requiring you to apply the protection as a separate build step.
Dotfuscator runs before the packaging steps of your build, making it easier to apply protection to apps distributed through a packaged format, such as Universal Windows (UWP) apps.
The integration automatically generates and maintains a Dotfuscator config file based on your project's references, ensuring that all of your code is protected, even those in different projects of your solution.
The Protect Your App page illustrates how easy it is to get started using these targets to protect a typical project. This section contains additional details useful for more advanced cases, such as how to choose which projects and configurations to protect.
PreEmptive.Dotfuscator.Common.targets
file.
For the deprecated MSBuild targets defined in PreEmptive.Dotfuscator.targets
, see Deprecated MSBuild Targets.
Once imported and enabled, these MSBuild targets run during the build automatically, after compilation but before packaging steps. If you want tighter control over how and when in the build process Dotfuscator runs, you can call the MSBuild tasks from your own MSBuild targets instead.
For technical details of the MSBuild targets, see Targets Reference.
Choosing What to Protect
Adding Dotfuscator to a build will increase your app's security, but it also adds additional time to your builds, introduces the risk of misconfiguration or runtime issues, and can make it harder to debug your app.
Given this, you should only use Dotfuscator for projects and build configurations that need it, such as the Release
configuration of an executable project.
Choosing Which Projects to Protect
When Dotfuscator is integrated into a Visual Studio project, it protects all assemblies in the project's output directory (e.g., ProjectDir/bin/Release
) that originated from the project's solution by default.
Because of this, you do not need to integrate Dotfuscator into all projects in your solution in order to protect all the assemblies you distribute.
DotfuscatorIncludeAsInput
MSBuild Property to the desired project file (e.g. Project.csproj
).
As an example, consider the following solution, MySolution.sln
, and its dependencies.
We want to distribute MyApp.exe
and its dependencies to untrusted users, and we want Dotfuscator to protect all of the code we own and distribute.
LibA.dll
and LibB.dll
are never distributed except alongside MyApp.exe
.
If we integrate Dotfuscator into just the MyApp
project and enable protection for the Release
configuration, Dotfuscator will protect three assemblies in the MyApp/bin/Release
directory:
LibA.dll
LibB.dll
MyApp.exe
Two assemblies will also appear in the MyApp/bin/Release
directory but not be protected:
ExtLib1.dll
ExtLib2.dll
Assemblies in output directories of other projects (e.g., LibA/bin/Release
) will also be unprotected.
There are three important points to learn from this example:
Dotfuscator protects only the assemblies in the integrated project's output directory.
While the copy of
LibA.dll
inMyApp/bin/Release
is protected, copies of the same assembly inLibA/bin/Release
andLibB/bin/Release
are not protected. A similar rule applies forLibB.dll
.Dotfuscator only needs to be integrated into final output projects, i.e. those whose output you intend to directly distribute.
In this example, integrating Dotfuscator into the
LibA
orLibB
projects is unnecessary. The only way an untrusted user would receive theLibA.dll
orLibB.dll
assemblies would be as dependencies ofMyApp
, and Dotfuscator protects the copies of these assemblies in theMyApp/bin/Release
directory.If your solution has multiple output projects, you will need to integrate Dotfuscator into each. In an alternate scenario, where
LibA
is also distributed to untrusted users (such as an API library for developers outside of your organization to reference), we would need to integrate Dotfuscator into both theMyApp
project and theLibA
project, ensuring Library Mode is enabled for the latter.Dotfuscator will protect only your code (by default).
Assemblies external to your solution, such as from NuGet (
ExtLib1.dll
) or a path on the filesystem (ExtLib2.dll
), are not protected by default. You can protect external assemblies on disk with theDotfuscatorIncludeAsInput
item metadata as described in "Controlling Which Assemblies Are Protected". This version of Dotfuscator does not support protecting assemblies that have already been packaged into a NuGet Package.
ProjectReference
Items recursively from the integrated project.
If one of your projects references another project's output assembly through a Reference
Item, the latter assembly will only be protected if it is manually included with the DotfuscatorIncludeAsInput
item metadata. See Controlling Which Assemblies Are Protected for more information.
Choosing Which Configurations to Protect
Builds in Visual Studio solutions and projects are parameterized by configuration.
By default, most solutions have two configurations, Debug
and Release
.
Each of the projects has matching configurations, so that when we build the solution in Release
, all of the projects themselves also build in their respective Release
configurations.
Once Dotfuscator is integrated into a project, you will need to know which of these configurations should be protected. Here are some guidelines for choosing what to protect:
You should apply Dotfuscator to all releasable build configurations. You want all builds given to untrusted users to be protected.
You should apply Dotfuscator to build configurations that will be tested. As with any static analysis tool, Dotfuscator cannot determine everything about your app's behavior. You will need to test the protected app to discover and address runtime issues.
You should NOT apply Dotfuscator to build configurations meant exclusively for debugging. Compared to debugging unprotected code, debugging obfuscated code is a much more challenging and limited experience. Even when you have the source code present and Dotfuscator is configured to automatically emit updated debugging symbols, some debugging features will be unavailable. Because of this, we don't recommend running Dotfuscator as part of your local development configurations.
Following these guidelines usually means you will protect the Release
configuration but not Debug
.
If your project has more configurations, you may also need to protect some of those; for example, in a Xamarin.iOS project, you should protect Release
, Ad-Hoc
, and AppStore
.
Controlling Which Assemblies Are Protected
When the Dotfuscator MSBuild targets are integrated into a project and enabled, Dotfuscator's default behavior is to protect the integrated project's assembly, as well as every assembly copied to the integrated project's output directory from other projects in the same solution. However, assemblies external to the solution will not be protected by default.
You can change this default behavior with DotfuscatorIncludeAsInput
.
This is a setting that can be applied both as an MSBuild property and as metadata on the MSBuild Reference
item.
Excluding Projects
To exclude a referenced project from Dotfuscator, add the DotfuscatorIncludeAsInput
tag to the project file (ex: .csproj
) of the project you want to exclude, and set the value to false
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Additional Property Tags -->
<DotfuscatorIncludeAsInput>false</DotfuscatorIncludeAsInput>
<!-- Additional Property Tags -->
</PropertyGroup>
</Project>
To re-enable protection on the assembly, you can either delete the tag entirely or set its value to true
.
Including External Assemblies
To add an external assembly as an input to Dotfuscator, add the DotfuscatorIncludeAsInput
tag to the Reference
item for that assembly and set the value to true
.
You can add the DotfuscatorIncludeAsInput
tag to any input project that references the external assembly, not just the project configured with Dotfuscator.
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Reference Include="ExternalAssembly">
<HintPath>../path/to/the/assembly/ExternalAssembly.dll</HintPath>
<DotfuscatorIncludeAsInput>true</DotfuscatorIncludeAsInput>
</Reference>
</ItemGroup>
</Project>
To disable protection on the assembly, change the DotfuscatorIncludeAsInput
tag's value to false
or remove it entirely.
DotfuscatorIncludeAsInput
tag will only work with the Reference
item, and is not supported on any ProjectReference
or PackageReference
items.
Finer Details
While the DotfuscatorIncludeAsInput
tags used in the examples above may have the same syntax, the first is a MSBuild Project Property, while the second is MSBuild Item Metadata.
The usage for both is essentially the same, although the Project Property must be added to a project file which does not directly integrate Dotfuscator.
The metadata, however, can be added to a Reference
item in any file.
The DotfuscatorIncludeAsInput
Project Property is applied recursively.
This means that any in-solution project referenced by a protected project will also be protected, while an in-solution project referenced by an excluded project will be excluded.
In the event that an in-solution project is referenced by both protected and excluded projects, the project in question will be protected by default.
Dotfuscator ignores DotfuscatorIncludeAsInput
metadata on Reference
items in excluded projects.
Importing the Targets
Dotfuscator's MSBuild targets file is PreEmptive.Dotfuscator.Common.targets
, found in the MSBuild components directory.
Thus these targets can be imported into a chosen project by editing the project file in a text editor (or by unloading, editing, and reloading in Visual Studio).
Since the MSBuild components directory can differ among machines, we recommend setting a
DotfuscatorMSBuildDir
property to represent the directory's path. See Handling Multiple Environments for details.Import the targets by adding the following line to the end of the project file, right before the closing
</Project>
tag:<Import Project="$(DotfuscatorMSBuildDir)/PreEmptive.Dotfuscator.Common.targets"/>
If your project uses the new SDK-based format introduced by .NET Core and .NET Standard, you will also need to replace the root
<Project>
element'sSdk
attribute with explicit imports to ensure Dotfuscator's targets are imported after the SDK's targets. For example, if your project file looks like this:<Project Sdk="Microsoft.NET.Sdk"> <!-- other tags, including those from step 1 --> <Import Project="$(DotfuscatorMSBuildDir)/PreEmptive.Dotfuscator.Common.targets"/> </Project>
then update it to look like this:
<Project> <!-- Sdk attribute has been REMOVED --> <!-- This import has been ADDED --> <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /> <!-- other tags, including those from step 1 --> <!-- This import has been ADDED --> <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /> <Import Project="$(DotfuscatorMSBuildDir)/PreEmptive.Dotfuscator.Common.targets"/> </Project>
In the two new
<Import>
tags withSdk
attributes, make sure that attribute's value is the same as theSdk
attribute that was originally on the<Project>
tag.
Setting Properties for the Targets
The targets are controlled by MSBuild properties, which must be declared earlier in the project file than the import statement for the targets. This section explains commonly-used properties; for a full list, see Available Properties.
DotfuscatorEnabled
By default, Dotfuscator does not run during the build.
To opt-in, set the DotfuscatorEnabled
property to true
:
<PropertyGroup>
<DotfuscatorEnabled>true</DotfuscatorEnabled>
</PropertyGroup>
However, you'll probably only want Dotfuscator to protect certain configurations, like Release
.
To only protect one configuration, specify a Condition
for DotfuscatorEnabled
:
<PropertyGroup>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'Release'">true</DotfuscatorEnabled>
</PropertyGroup>
To protect multiple configurations (e.g., for Xamarin.iOS apps), repeat the definition with a different Condition
for each configuration:
<PropertyGroup>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'Release'">true</DotfuscatorEnabled>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'Ad-Hoc'">true</DotfuscatorEnabled>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'AppStore'">true</DotfuscatorEnabled>
</PropertyGroup>
Alternatively, instead of declaring DotfuscatorEnabled
in its own <PropertyGroup>
, you can declare it in pre-existing groups that are already selected based on the configuration and target platform.
For example:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin/Release/</OutputPath>
<!-- ...other properties... -->
<!-- Enable Dotfuscator for Release|AnyCPU -->
<DotfuscatorEnabled>true</DotfuscatorEnabled>
</PropertyGroup>
If you go this route, don't forget to set DotfuscatorEnabled
for all of a configuration's target platforms.
For instance, if you want to protect the Release
configuration, check for <PropertyGroup>
sections for Release|AnyCPU
, Release|x86
, Release|iPhone
, etc.
DotfuscatorGenerateConfigFileIfMissing
To perform protection, Dotfuscator requires a config file (named DotfuscatorConfig.xml
by default).
When setting up Dotfuscator's MSBuild targets, you should configure the targets to generate this file.
To do so, set the DotfuscatorGenerateConfigFileIfMissing
property to true
:
<PropertyGroup>
<DotfuscatorGenerateConfigFileIfMissing>true</DotfuscatorGenerateConfigFileIfMissing>
</PropertyGroup>
However, once the config file is generated (i.e., after the initial build), you should disable this feature to avoid certain kinds of build issues.
Initial Build
After importing the targets and setting the necessary properties, you can build the project in Visual Studio or through the MSBuild command line.
Be sure to select a configuration for which you have set DotfuscatorEnabled
to true
.
The first time you build, assuming you set DotfuscatorGenerateConfigFileIfMissing
to true
, Dotfuscator will produce a new config file and emit a warning to this effect.
You can ignore the warning on the initial build; it's intended to signal possible build issues in subsequent builds, where the config file is expected to already exist.
Every time you build, Dotfuscator will apply protection to the assemblies in the project's output directory (e.g., bin/Release
).
For a detailed example of which assemblies are protected, see Choosing Which Projects to Protect.
Dotfuscator also produces report files as part of every build.
When the build completes, you can run the app locally to ensure it continues to behave as expected.
About the Config File
Dotfuscator uses a config file to control its various protection settings.
By default, this config file is saved as DotfuscatorConfig.xml
in your project directory.
You can change the path of the config file by setting the DotfuscatorConfigPath
property in your project file.
(Note that if the config file has already been generated at the old path, you will need to move it to the new path to retain your settings.)
During the initial build, Dotfuscator generates a config file which offers a default level of protection. As part of subsequent builds, Dotfuscator will keep the config file up-to-date with any changes you make to project references in the solution.
You can customize and enhance Dotfuscator's protection by editing this config file with the Dotfuscator Config Editor. For a detailed example, see Enhance Protection.
The config file is an input to your build process. You should:
Add this file to version control. This allows build agents and fellow team members to build the project with the same protection settings. You can also track your team's changes to the file, and thus the protection settings, over time.
Disable config file generation. If Dotfuscator can't find the config file during a build, it will automatically generate one. While this was helpful for the initial build, leaving this feature enabled for subsequent builds will cause these builds to pass, even if the config file is missing. If the config file is removed by accident, this could lead to builds that are only protected with the default settings, rather than your customized protection configuration.
To disable the config file generation feature and have the build error if the config file is missing, edit your project file to change the following property to
false
:<DotfuscatorGenerateConfigFileIfMissing>false</DotfuscatorGenerateConfigFileIfMissing>
Never distribute this file outside of your organization. Sensitive information, such as the names of source code elements, can reside in the config file.
Finally, note that the config file appears under your project's node in Visual Studio's Solution Explorer. This is because the MSBuild targets add the config file as an MSBuild item to your project, which ensures Visual Studio will consider changes to the config file when deciding whether to build the project.
About the Report Files
Dotfuscator generates various report files whenever it runs as part of a build. The following report files can be generated, depending on the protection settings:
Renaming.xml
: the renaming report file, also known as the renaming map file.Removal.xml
: the removal report file.SmartObfuscation.xml
: the Smart Obfuscation report file.
By default, these reports are stored in the project's DotfuscatorReports
subdirectory.
You can change the paths for the report files by editing the config file using the Config Editor's Settings tab.
configuration
and platform
, corresponding to the current build configuration and platform.
You can use these values in your custom report file paths to ensure reports from different build configurations and platforms stay separate.
Report files are outputs of a build, much like the assemblies themselves (in the bin
directory).
You should:
Ignore these files in version control. These files are updated every time Dotfuscator runs as part of the build, so your version control should ignore the
DotfuscatorReports
subdirectory.Archive these files to a secure, versioned location when releasing the app. When Dotfuscator's Renaming obfuscation is enabled, stack traces from the app will contain obfuscated type and method names. This can make it difficult to diagnose issues reported by customers.
To solve this, one of the reports Dotfuscator produces, the renaming map file, associates each renamed code element with the element's original name. When you release your app, you should copy this file (and the other reports) to a secure location. Then, if a customer gives you an obfuscated stack trace, you can pass it and the archived map file to Dotfuscator's tool for decoding obfuscated stack traces, which will produce a stack trace matching the original source code.
Never distribute these files outside of your organization. The information in these reports can be used to undo parts of Dotfuscator's protection, even by those who do not have Dotfuscator.
Subsequent Builds
Once you've built the project once and then configured the config file and report files as recommended, you can continue building your project locally. If you push your changes to your team's version control, you will also start getting protected builds from your automated build system.
You can continue to develop and test your app with Dotfuscator's protection. You can also enhance this protection.
MSBuild Tasks
Dotfuscator includes MSBuild tasks that can be called from a customized MSBuild project.
The most commonly-used task is the Dotfuscate
task, which calls Dotfuscator to perform protection specified by an existing Dotfuscator config file.
For a full list of tasks and their associated parameters, see MSBuild Task Reference.
Referencing the Dotfuscate Task
The Dotfuscator MSBuild tasks library, PreEmptive.Dotfuscator.Tasks.dll
, is located in the MSBuild components directory.
The tasks are exposed in the PreEmptive.Tasks
namespace.
To reference the Dotfuscate
task for use in your MSBuild project:
Since the MSBuild components directory can differ among machines, we recommend using a
DotfuscatorMSBuildDir
property to represent the directory's path. See Handling Multiple Environments for details.Add the following as a child of your project file's root
<Project>
element. You should place it after theDotfuscatorMSBuildDir
property is defined, but before any targets where you intend to use theDotfuscate
task.<UsingTask TaskName="PreEmptive.Tasks.Dotfuscate" AssemblyFile="$(DotfuscatorMSBuildDir)/PreEmptive.Dotfuscator.Tasks.dll" />
If you are using a version of MSBuild older than 15.0, then replace
$(DotfuscatorMSBuildDir)/
with$(DotfuscatorMSBuildDir)/legacy/
. For details on the differences between the default "modern" tasks and the "legacy" tasks, see MSBuild Task Reference.
Calling the Dotfuscate Task
Once referenced, you can then call the Dotfuscate
task from a custom MSBuild target.
As a simple example, consider the following AfterBuild
target in a C# project:
<Target Name="AfterBuild">
<Dotfuscate ConfigPath="MyDotfuscatorConfig.xml" License="$(DotfuscatorLicense)">
<Output
TaskParameter="OutputAssemblies"
ItemName="MyDotfuscatorOutputAssemblies" />
</Dotfuscate>
<Message
Importance="high"
Text="Dotfuscator wrote: @(MyDotfuscatorOutputAssemblies)" />
</Target>
This AfterBuild
declaration overrides a target predefined by MSBuild.
As a result, MSBuild will run the target after running the normal build steps.
We start by having the target call the Dotfuscate
task.
We provide three task parameters, two inputs and one output:
We set the required
ConfigPath
input parameter toMyDotfuscatorConfig.xml
. Dotfuscator will perform the protection specified by that Dotfuscator config file, located in the project's directory.We set the optional
License
input parameter to the value in theDotfuscatorLicense
MSBuild property. If you specified this property in a.dotfuscator.user.props
file, make sure you import that file into your project before usingDotfuscate
; e.g.:<Import Project="$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.dotfuscator.user.props" Condition="Exists('$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))/.dotfuscator.user.props')"/>
When this property is set, Dotfuscator will activate itself when it runs. If you don't set this property, you will need to activate in a different way.
We specify that MSBuild items from the
OutputAssemblies
output parameter will be stored as a set of MSBuild items namedMyDotfuscatorOutputAssemblies
. This output parameter exposes the full paths to assemblies Dotfuscator wrote.
We then log the paths Dotfuscator wrote by having the target call the Message
task.
For a full list of parameters, see Dotfuscate Task.
Deprecated MSBuild Targets
For compatibility with existing projects, Dotfuscator includes a separate set of MSBuild targets defined in the PreEmptive.Dotfuscator.targets
file.
Because these targets are not designed for easy integration into an existing Visual Studio or MSBuild project, we recommend either using the newer MSBuild targets to integrate Dotfuscator into your project or calling the appropriate MSBuild tasks from your own target.