Skater .NET Obfuscator

Automating .NET Obfuscation in Visual Studio Builds

A hands-on walkthrough for embedding Skater .NET Obfuscator into post-build events - so every Release binary is protected before it reaches testing, packaging, or the customer.

Bottom line: Insert a Skater CLI command into the project’s Post-build event command line. After the compiler produces the assembly, Skater immediately obfuscates it in place. Use the documented flags (-SOURCE, -OUTPUT, -KEY, -WRITELOG, -ALLPRIVATE, -CONCEALSTRINGS, -FLOW), set parallel builds to 1, run your tests against the protected binary, then package. CLI automation requires the Pro or Enterprise edition.
Compile → Obfuscate → Test → Package

The objective is straightforward: the binary that leaves the developer machine (or CI agent) is already protected. No manual GUI step is needed for each release.

The problem with manual obfuscation

Manual obfuscation doesn’t scale

Using the Skater GUI for a one-off demo works fine. But it breaks down when you have:

If obfuscation is optional or forgotten, an unprotected assembly reaches customers. Integrating the CLI into the Visual Studio build event makes protection automatic and repeatable.

Small C# example (context)

Assume a simple class-library or executable project that produces MyApp.dll (or MyApp.exe) under bin\Release\net8.0\. The project may be strong-named with KeyFile.snk in the project root. After a normal build the assembly is fully readable by ILSpy. The post-build step below replaces that assembly with an obfuscated version before any further packaging occurs.

What happens without build integration

Step-by-step Skater configuration in Visual Studio

  1. Create (or confirm) settings in the Skater GUI
    Launch Skater, load the Release assembly once, choose the desired protection options (private/public renaming, string encryption, control-flow intensity, WPF/BAML if applicable), and save a named settings profile. The CLI can later reuse that profile or accept explicit flags.
  2. Open Project Properties
    In Solution Explorer right-click the project → Properties.
  3. Go to Build Events
    Select the Build Events tab.
  4. Paste the Post-Build command
    In the Post-build event command line box insert the command shown below. Restrict it to Release configurations if you prefer (see the conditional example later).
  5. Disable parallel project builds
    Tools → Options → Projects and Solutions → Build and Run → set Maximum number of parallel project builds to 1. This prevents file-lock races while Skater rewrites the assembly.
  6. Build the project
    Perform a Release build. The Output window should show Skater running after the compiler finishes. Check for a zero exit code and the presence of the log file.
  7. Test, then package
    Run your test suite against the protected binary, then proceed to packaging / installer / publish steps.

Exact Post-Build command

The documentation provides the following command (line continuation with ^ is for readability inside the Visual Studio dialog; you may also place it on a single line):

"C:\Program Files (x86)\RustemSoft\Skater\Skater.exe" ^
  -SOURCE="$(TargetPath)" ^
  -OUTPUT="$(TargetPath)" ^
  -KEY="$(ProjectDir)KeyFile.snk" ^
  -WRITELOG="$(TargetDir)Skater.log" ^
  -ALLPRIVATE ^
  -CONCEALSTRINGS ^
  -FLOW
Path note: Adjust the path to Skater.exe if you installed to a different location (for example C:\Program Files\Rustemsoft LLC\Skater\Skater.exe or a custom folder). Always test the command from a plain Command Prompt first.

Parameter breakdown

Parameter Purpose
-SOURCE="$(TargetPath)" Input assembly. $(TargetPath) expands to the full path of the file the compiler just produced (e.g. …\bin\Release\net8.0\MyApp.dll).
-OUTPUT="$(TargetPath)" Output path. Writing back to the same location overwrites the original with the protected version so every subsequent step (tests, packaging) automatically uses the obfuscated binary.
-KEY="$(ProjectDir)KeyFile.snk" Strong-name key used to re-sign the assembly after modification. Omit this flag if the project is not strong-named.
-WRITELOG="$(TargetDir)Skater.log" Writes a diagnostic log next to the output assembly. Useful for diagnosing failures on build servers.
-ALLPRIVATE Obfuscates private (and typically internal) members for deeper name protection.
-CONCEALSTRINGS Enables string encryption so literals are not visible in plain text inside the assembly.
-FLOW Applies control-flow obfuscation (Lightweight by default in most configurations).

You can also invoke a previously saved settings profile by name (created in the GUI) instead of listing every flag:

"C:\Program Files (x86)\RustemSoft\Skater\Skater.exe" MySavedSettingsProfile

The explicit-flag form shown above is preferred when you want the command itself to be self-documenting and version-controlled.

Run only on Release builds

To avoid slowing Debug builds, wrap the command with a configuration check:

if "$(ConfigurationName)" == "Release" (
  "C:\Program Files (x86)\RustemSoft\Skater\Skater.exe" ^
    -SOURCE="$(TargetPath)" ^
    -OUTPUT="$(TargetPath)" ^
    -KEY="$(ProjectDir)KeyFile.snk" ^
    -WRITELOG="$(TargetDir)Skater.log" ^
    -ALLPRIVATE ^
    -CONCEALSTRINGS ^
    -FLOW
)

.bat script example

For local testing or for use from a CI agent that does not expand Visual Studio macros, a small batch file is convenient:

@echo off
setlocal

REM Adjust these paths to match your machine / pipeline
set SKATER="C:\Program Files (x86)\RustemSoft\Skater\Skater.exe"
set ASSEMBLY=%~dp0bin\Release\net8.0\MyApp.dll
set KEYFILE=%~dp0KeyFile.snk
set LOGFILE=%~dp0bin\Release\net8.0\Skater.log

echo Obfuscating %ASSEMBLY% ...
%SKATER% -SOURCE="%ASSEMBLY%" -OUTPUT="%ASSEMBLY%" -KEY="%KEYFILE%" -WRITELOG="%LOGFILE%" -ALLPRIVATE -CONCEALSTRINGS -FLOW

if %ERRORLEVEL% neq 0 (
  echo Skater failed with exit code %ERRORLEVEL%
  exit /b %ERRORLEVEL%
)

echo Done. Log written to %LOGFILE%
endlocal

Save as obfuscate.bat next to the project (or on the build agent), then call it from a post-build event or from a pipeline task:

call "$(ProjectDir)obfuscate.bat"

Resulting output

When the command succeeds you typically see console output similar to:

Obfuscating C:\src\MyApp\bin\Release\net8.0\MyApp.dll ... Analyzing assembly... Renaming symbols... Encrypting strings... Applying control-flow transformations... Re-signing assembly... ✔ Protected successfully. Log written to C:\src\MyApp\bin\Release\net8.0\Skater.log

The file at $(TargetPath) is now the protected assembly. Opening it in ILSpy shows renamed identifiers, encrypted strings, and (when control-flow is enabled) hard-to-follow method bodies. The log file contains timestamps, selected options, and any warnings.

Keep the rename-map XML that Skater can produce (if enabled in your settings). It allows you to decode obfuscated stack traces during support.

Testing the obfuscated application

  1. Build in Release configuration and confirm the post-build event runs without errors.
  2. Inspect Skater.log for warnings (missing key, excluded members, etc.).
  3. Run the full automated test suite against the binary that now sits in the output folder.
  4. Manually exercise critical paths (licensing, payments, UI) on the protected build.
  5. Open the protected assembly in ILSpy / dnSpy and verify that names and strings are no longer readable in plain form.
  6. Only after the above steps succeed, proceed to packaging or publishing.

Common failures and fixes

Symptom Likely cause Fix
File is locked / access denied Parallel project builds or another process still has the DLL open Set parallel project builds to 1; ensure no other tool is locking the output file
“Skater.exe is not recognized” Wrong path or CLI not installed (Basic edition) Verify the full path to Skater.exe; upgrade to Pro/Enterprise for CLI support
Strong-name validation fails at runtime Assembly was modified but not re-signed Supply a valid -KEY path or disable strong-naming if not required
Setup project ships unobfuscated binary “Primary Output” captured the file before Skater ran, or PreBuildEvent was not used on the setup project Obfuscate the application project first; add the compiled (already protected) file manually to the setup project, or use PreBuildEvent on the deployment project as described in the official docs
Post-build runs on every Debug build and slows iteration No configuration filter Wrap the command in if "$(ConfigurationName)" == "Release"
Exit code non-zero, log shows missing settings Flags conflict with a saved profile or required options are absent Test the exact command line from a Command Prompt; simplify flags or rely on a known-good saved profile

Production recommendations

Setup / Deployment projects: When using a Visual Studio Setup project, prefer protecting the application assemblies first, then adding the already-obfuscated files to the setup project. Relying on “Primary Output” can silently package the unprotected binary. The official documentation also shows using PreBuildEvent on the deployment project itself when appropriate.

FAQ

Which edition do I need for post-build automation?
Pro or Enterprise. The free Basic edition includes the GUI and core protection features but does not ship the command-line interface required for unattended post-build or CI use.
Can I call a saved settings profile instead of listing flags?
Yes. After saving a profile in the GUI you can run Skater.exe MyProfileName. Explicit flags remain useful when you want the command line to be self-contained and easy to review in source control.
Does overwriting $(TargetPath) break incremental builds?
Visual Studio still considers the project up-to-date based on inputs and outputs. Because the post-build step replaces the output file with a new version that has the same name, subsequent packaging steps correctly pick up the protected assembly. For best results keep parallel builds disabled.
Where should Skater.exe live on a build server?
Install it in a known location (or check the binaries into a tools folder under source control) and reference that absolute or relative path from the post-build event or pipeline script. Enterprise edition supports internet-free build servers.
What if my solution has many projects?
Add the post-build command only to the projects whose output assemblies will be distributed. Protect dependency order (or set parallel builds to 1) so that a project is never consumed by another project while Skater is still rewriting it.

Related SkaterPro guides

Download Skater Read the full manual