Building on a Mac with Dotfuscator 6 In Azure DevOps

PreEmptive is dedicated to protecting your apps, wherever and however they are built. Our recent release of the Dotfuscator 6.0 beta adds cross-platform support, allowing you to protect your application on other platforms besides Windows. This allows for intuitive integration into Xamarin.iOS projects on macOS.

In this blog post, we’ll go through the steps required to bring this functionality to your existing Azure DevOps Pipelines and AppCenter builds.


This post will assume that you have an existing Xamarin.iOS build and simply want to integrate Dotfuscator into it.

Host Dotfuscator’s NuGet Package

Before we can integrate Dotfuscator into our build, we have to host the PreEmptive.Protection.Dotfuscator.Pro NuGet package(or the Eval package if you are currently evaluating). For this example, we will host the package on a private feed on Azure DevOps Artifacts.

To begin, download the Dotfuscator 6 Beta NuGet Package from your downloads page on the PreEmptive website, and publish it to your hosted feed. If you have successfully pushed the package, it should show up in your list of packages:

dot nuget pushed

Integrate Dotfuscator Into Project Files

Follow the Protect Your App instructions for Xamarin to integrate Dotfuscator into your project files.

Azure DevOps Pipelines

The following steps will use YAML Pipelines in Azure DevOps (AzDO).

Configure macOS for Dotfuscator 6 Beta

Dotfuscator Beta 6 cross-platform support currently requires .NET Core 3.x SDK, which the current AzDO images do not have installed. There is an open issue for adding this support, but for the moment adding the following command near the start of your build will install the latest .NET Core SDK for you:

curl -sSL | bash

Note that the AzDO images default to an older version of Mono which is not supported by the current Dotfuscator beta. Running the following command will cause a newer version of Mono to be used by default:

echo "##vso[task.prependpath]/Library/Frameworks/Mono.framework/Versions/6.4.0/bin"

These commands can be run in a single step near the start of your pipeline as follows:

- task: Bash@3
    targetType: 'inline'
    script: |
      curl -sSL | bash
      echo "##vso[task.prependpath]/Library/Frameworks/Mono.framework/Versions/6.4.0/bin"

Install Dotfuscator 6 Beta as Part of the Build

The Dotfuscator NuGet package must be installed prior to any restore or build steps. This can be done with a custom NuGet command step:

- task: NuGetCommand@2
    command: 'custom'
    arguments: 'install PreEmptive.Protection.Dotfuscator.Pro -OutputDirectory $(Agent.TempDirectory) -PreRelease -x -Source[AzDO Org]/[AzDO Project]/_packaging/[AzDO Feed]/nuget/v3/index.json'

Note the use of the -PreRelease option (since this is a beta package) as well as the -x option to exclude the version name from the directory Dotfuscator is installed to.

Configure Build Variable

Define a secret variable called Dotfuscator_License and set its value to the Dotfuscator License Key you have been given from PreEmptive.

dot license var

Set Environment and MSBuild Properties Where Needed

Since we install Dotfuscator to a temp directory on the Azure build agents, but our project files are looking for the Dotfuscator targets file elsewhere, we need to tell NuGet and MSBuild where to find it during those operations.

During a NuGet restore, NuGet can use the environment variable NUGET_RESTORE_MSBUILD_ARGS to define additional arguments. Update any NuGet restore calls to use the env tag like so:

- task: NuGetCommand@2
    command: 'restore'
    restoreSolution: '**/*.sln'
  env: { "NUGET_RESTORE_MSBUILD_ARGS": '/p:DotfuscatorMSBuildDir="$(Agent.TempDirectory)/PreEmptive.Protection.Dotfuscator.Pro/tools/msbuilddir"' }

Any calls to MSBuild should likewise be updated to define DotfuscatorMSBuildDir and to pass in the Dotfuscator license key using the variable defined above:

- task: XamarinAndroid@1
    projectFile: '**/*droid*.csproj'
    outputDirectory: '$(outputDirectory)'
    configuration: '$(buildConfiguration)'
    msbuildArguments: '/p:DotfuscatorMSBuildDir="$(Agent.TempDirectory)/PreEmptive.Protection.Dotfuscator.Pro/tools/msbuilddir" /p:DotfuscatorLicense="$(Dotfuscator_License)"'
    jdkOption: 'JDKVersion'

Run the Pipeline

Given the above steps and settings, you should be able to run the pipeline and see Dotfuscator protecting your application!

pipeline output

AppCenter Build

By default, AppCenter already takes care of installing the .NET Core 3.1 SDK and switching to the newer version of Mono, so those steps are unnecessary. Instead we use a post clone script and some environment variables to configure the build as necessary.

Environment Variables

We will define five environment variables in our AppCenter Build:

NUGET_USER_PASSWORD: A secret variable set to a personal access token (PAT) for package read access to the artifact feed of your AzDO organization, or other authentication information if using another private feed.

NUGET_USER_NAME: When using a PAT, this value is irrelevant, but still needs to be defined.

NUGET_FEED_URL: The URL to the NuGet feed hosting the PreEmptive.Protection.Dotfuscator.Pro NuGet package.

DotfuscatorLicense: A secret variable set to the Dotfuscator License Key you have been given from PreEmptive.

DotfuscatorMSBuildDir: Should be set to $(APPCENTER_SOURCE_DIRECTORY)/PreEmptive.Protection.Dotfuscator.Pro/tools/msbuilddir.

When all the environment variables are configured, they should look something like this:

appcenter vars

Post Clone Script

Next to the project file, either create a new file, or add the following command to your existing post clone script:

nuget install PreEmptive.Protection.Dotfuscator.Pro -OutputDirectory $APPCENTER_SOURCE_DIRECTORY  -PreRelease -x -Source $NUGET_FEED_URL

Run the AppCenter Build

Given the above steps and settings, you should be able to run the Build and see Dotfuscator protecting your application!

dot appcenter build

Further Reading

For more details on utilizing the Dotfuscator NuGet package on these and other types of build agents, be sure to read the appropriate section of the Dotfuscator documentation!