PreEmptive Protection - Dotfuscator 4.31
User Guide

Understanding Instrumentation

Dotfuscator's Instrumentation features add pre-built application usage, feature usage, exception tracking, and system metrics to your application, without requiring you to write any additional code. This process is known as code injection. An application that undergoes this process is known as an injected application. At runtime, the code injected into the application will transmit telemetry to a PreEmptive Analytics endpoint.

The development workflow for injecting instrumentation code into an application is similar to that for obfuscating an assembly. Both require configuring Dotfuscator to work with the specific assemblies, and both produce a set of output assemblies that match the input assemblies. The only difference is the specific configuration elements that are used. The output assemblies will contain all the run-time code necessary to collect and deliver the telemetry data.

The diagram below illustrates the workflow from the developer's point of view.

When using code injection, other Dotfuscator features are available. The injected runtime code is annotated with obfuscation attributes so user configuration (beyond what is necessary for the input assemblies and the details of your application's code) is not required to perform renaming, removal, or other transforms on the code Dotfuscator injects in to your application.


Instrumentation is configured via attributes and a set of project-wide options. For details, see:

Supported Application Types

Dotfuscator can inject Instrumentation code for all .NET assemblies except for the following:

  • Managed C++ input assemblies containing native and managed code
  • Multi-module input assemblies
  • Input assemblies that target .NET 1.0
  • Xamarin assemblies
  • Unity assemblies


As the injected application runs, the injected code generates messages to mark information about tracked events, such as a "Session Start" message to mark the start of a session for session tracking.

When a sufficient number of messages have been generated, and the injected application is not under high load, the messages will be packaged into an HTTP POST body, called an envelope, which is then transmitted to the configured endpoint.

The process of generating these messages and sending them to an endpoint is called telemetry. The messages themselves may also be called telemetry.

Envelopes, and the messages within them, are identified by the business, application, and binary information configured for the application.

See Example PreEmptive Analytics Enabled Application to see the contents of messages containing PreEmptive Analytics data.

End User Opt-in

Injected applications can provide the end user an option to enable or disable telemetry. The injected Instrumentation code will honor this option, if it is provided by the application code, during Instrumentation setup.

The preference is communicated via a source defined with the SetupAttribute called OptInSource. The source defines a bool value which is true if the user opts-in and false if the user opts-out. If no source is provided for a SetupAttribute, the injected code will act as if the user opted-in.

For instance, consider the following attribute and its properties:

At runtime, when InstrumentationExample.Program.Main is called, the injected code will first call the static method InstrumentationExample.Program.OptIn(). If the result of the call is true, messages will be generated and transmitted during the application's run. If the result of the call is false, most regular messages will not be generated.

There are a couple of cases where messages will still be generated and transmitted, regardless of the opt-in setting:

Personally Identifiable Information

Whether personally identifiable information (PII) is omitted from Instrumentation tracking can be configured with the OmitPII property of the SetupAttribute.

Offline Storage

If an injected application cannot connect to the specified endpoint at runtime, generated messages can be stored and then transmitted when connectivity is restored. Messages are stored on disk in Isolated Storage. This behavior is enabled by default, and default connectivity detection code will be injected into instrumented applications.

You can completely turn off Offline Storage by configuring the OfflineStateSourceElement property of the SetupAttribute. Generated messages will not be stored when the application is unable to connect to the specified endpoint and will, therefore, be lost.

You also have the ability to write your own network detection code and to make the resulting network connectivity state available to the injected code via a boolean source defined with the SetupAttribute called OfflineStateSource.

The application can also be notified of the success or failure of an attempt to store messages to Offline Storage via a boolean sink defined with the SetupAttribute called OfflineStorageResultSink. If this sink is configured, you can write code to react to the success or failure of Offline Storage attempts.

Application Instance ID Reporting

You have the option to include an application instance identifier (e.g. a serial number) in generated messages. If desired, the application can provide this ID in a source defined with the SetupAttribute called InstanceIdSource. Injected instrumentation code will request this string ID from that source and send it along with the rest of the telemetric data.


PreEmptive Solutions offers a number of endpoints to which your application can send messages.

PreEmptive Analytics Workbench

PreEmptive Analytics Workbench accepts, processes, transforms, and aggregates telemetry for display in a web browser. It is highly configurable and customizable so that it can provide role-based, real-time visibility into application usage, adoption, user behavior, and software quality - saving you time and money.

To learn more, please read about PreEmptive Analytics Workbench on our website.

Community Workbench

PreEmptive Solutions hosts a publicly-accessible Analytics Workbench, called the Community Workbench. This allows you to monitor how many times your application is run, which features are being used, and how stable it is, for free.

Note: The Community Workbench comes with no guarantees or service level agreements. All data received is visible to all users, without authentication. Certain features of the Community Workbench are restricted, compared to the commercial product.

To configure your application to send to the Community Workbench:

To view your data:

Analytics API

The Analytics API contains code related to sending messages, managing offline storage, and general instrumentation setup.

There are two ways that this API can be accessible from your application's injected code:

  1. Dotfuscator can merge (inject) the Analytics API's runtime code into one of the input assemblies.

    • In this scenario, you do not need to separately distribute the PreEmptive Analytics DLL.
  2. Dotfuscator can output the Analytics API's runtime code in a separate assembly and add the appropriate assembly references to the input assemblies.

    • If any of the input assemblies are strong named, Dotfuscator will strong name the runtime DLL and sign it transparently; if none are strong named, Dotfuscator will not strong name the runtime DLL.

    • In this scenario, you must distribute the new DLL along with your application.

    • Dotfuscator will still need to inject instrumentation helper methods into each assembly that is configured for instrumentation.

The Merge Runtime option which controls this behavior is a general injection option. You can access injection options in both the standalone user interface and the Visual Studio integration.

Regardless of how you set this option, Dotfuscator still needs to inject code into one of the input assemblies in order to use the Analytics API. Dotfuscator performs a dependency analysis of the input assemblies in order to choose the best one. It chooses in such a way as to minimize new dependencies among input assemblies; however, adding new dependencies is unavoidable in some cases.

You can override the assembly that this code will be injected into by adding a Project Property with the name "accesspoint" and setting its value to the name of the assembly where the code will be inserted. You can add this Project Property in the standalone user interface or in the Visual Studio integration.

Dotfuscator Version Copyright © 2017 PreEmptive Solutions, LLC