WiseOwl.Demeanor.MSBuild
6.1.1
Prefix Reserved
dotnet add package WiseOwl.Demeanor.MSBuild --version 6.1.1
NuGet\Install-Package WiseOwl.Demeanor.MSBuild -Version 6.1.1
<PackageReference Include="WiseOwl.Demeanor.MSBuild" Version="6.1.1" />
<PackageVersion Include="WiseOwl.Demeanor.MSBuild" Version="6.1.1" />
<PackageReference Include="WiseOwl.Demeanor.MSBuild" />
paket add WiseOwl.Demeanor.MSBuild --version 6.1.1
#r "nuget: WiseOwl.Demeanor.MSBuild, 6.1.1"
#:package WiseOwl.Demeanor.MSBuild@6.1.1
#addin nuget:?package=WiseOwl.Demeanor.MSBuild&version=6.1.1
#tool nuget:?package=WiseOwl.Demeanor.MSBuild&version=6.1.1
WiseOwl.Demeanor.MSBuild
Build-time obfuscation for .NET projects. From the original .NET obfuscator, shipping since 1999.
Add a <PackageReference>, set one MSBuild property, and dotnet build
runs obfuscation as part of every Release build. No global tool install
required, no separate CI step, no per-machine setup. dotnet restore
pulls the package; the bundled obfuscator runs as a build target.
Learn more at www.wiseowlsoftware.com
Install
dotnet add package WiseOwl.Demeanor.MSBuild
That's it. Release builds auto-obfuscate; Debug builds and test projects are auto-skipped. No csproj edit required.
dotnet build -c Release
# → bin/Release/<tfm>/MyApp.dll is obfuscated, in place
The package's built-in default is equivalent to:
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<Obfuscate>true</Obfuscate>
</PropertyGroup>
Change true to false if you want to disable obfuscation for some
reason.
Test projects (anything where Microsoft.NET.Test.Sdk has set
IsTestProject=true — xunit / mstest / nunit) auto-skip even on
Release; obfuscating a test assembly would break the runner's
reflection-based discovery.
What it looks like
// Your code
public class PriceCalculator
{
private readonly decimal _discount = 0.10m;
public decimal Apply(decimal price)
{
Console.WriteLine($"Discount: {_discount:P}");
return price - (price * _discount);
}
}
After Enterprise obfuscation, decompiled with ILSpy:
public class a
{
private decimal m_a;
public decimal (decimal a)
{
b.c(b.a("\u0003\rÍÆ0\u001C"), this.m_a);
return a - (a * this.m_a);
}
}
Method name is literal whitespace — invalid C# at the parser. Strings encrypted into a decryptor call. Try to recompile:
$ dotnet build
CS1001: Identifier expected
Build FAILED.
Plus integer constants encrypted, control flow obfuscated, anti-tamper
and anti-debug injected. The decompiler shows you something — but
it's unreadable, won't compile, and the literal
"Discount: {_discount:P}" is gone. (Real ILSpy output.)
Common properties
| Property | Default | Effect |
|---|---|---|
Obfuscate |
true for Release builds (skipped for test projects); false for Debug |
Enable/disable obfuscation for this build |
DemeanorOut |
$(TargetDir). |
Output directory; default replaces the unobfuscated build output in place |
DemeanorIncludePublics |
false |
Also rename public/protected symbols |
DemeanorIncludeDeps |
false |
Also obfuscate co-located private deps |
DemeanorReport |
true |
Emit <assembly>.report.json for crash-trace decoding via demeanor deobfuscate |
DemeanorQuiet |
true |
Suppress non-error output |
Every Demeanor CLI option is exposed as a <Demeanor*> MSBuild
property — disable individual passes (<DemeanorStringEncryption>,
<DemeanorCfg>, <DemeanorAntiTamper>, etc.), tune thresholds
(<DemeanorProxyThreshold>16</DemeanorProxyThreshold>), or pass through
strong-name keys (<DemeanorKeyFile>...</DemeanorKeyFile>). The targets
file at build/WiseOwl.Demeanor.MSBuild.targets documents the full
property surface.
Exclusions as MSBuild items
<ItemGroup>
<DemeanorExclude Include="MyApp.Models.ApiResponse" />
<DemeanorExcludeRegex Include=".*ViewModel$" />
<DemeanorExcludeAssembly Include="ThirdParty.Library" />
</ItemGroup>
Per-project obfuscation policy lives in the .csproj next to the rest
of your build configuration — versioned, code-reviewed, and CI-friendly.
License key
Set the DEMEANOR_LICENSE environment variable (CI secret, shell
profile, etc.). There is no <DemeanorLicense> MSBuild property by
design — license keys do not belong in source-controlled .csproj
files.
Without an Enterprise key, Demeanor degrades to Community-tier basic renaming. All advanced protection — encryption, control-flow obfuscation, call hiding, anti-tamper, anti-debug, aggressive renaming, and the AI-assisted workflow — is Enterprise-only.
Licensing
Per-company licensing — no seat counting, no machine locking. RSA-signed keys validated entirely offline.
| Tier | Features |
|---|---|
| Community | Symbol renaming, alpha naming, single assembly |
| Enterprise | All protection passes + framework auto-detection + AI-assisted workflow |
Pricing and purchase: www.wiseowlsoftware.com/pricing.
Companion: WiseOwl.Demeanor global tool
For ad-hoc CLI use (demeanor audit, demeanor check,
demeanor deobfuscate, inspector, and the Claude Code /obfuscate
workflow with built-in MCP server), install the global tool:
dotnet tool install -g WiseOwl.Demeanor
This MSBuild package and the global tool share the same self-contained
obfuscator binary internally — install whichever (or both) matches your
workflow.
Documentation
Full documentation including MSBuild property reference, exclusion patterns, CI/CD integration (GitHub Actions, Azure DevOps, GitLab CI), framework-by-framework guidance, and troubleshooting:
About Wise Owl Software
Demeanor is published by Wise Owl Software, founded by Brent Rector in 1990. Brent has been writing software for over five decades and spent two decades at Microsoft as a Principal Software Architect — a decade directly on the Windows operating system itself, plus years on Visual Studio, the Windows SDK, and .NET. Demeanor's first beta shipped in June 2000 alongside .NET Beta 1, and the same author has continuously developed and maintained it across every release since.
Copyright (c) Wise Owl Software. 1999-2026. All Rights Reserved. Commercial product; see LICENSE for the EULA.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Every Demeanor option is exposed as a <Demeanor*> MSBuild property, and every protection takes a level rather than an on/off switch: <DemeanorRename>off|on|aggressive</DemeanorRename>, <DemeanorCfg>none|reorder|predicates|flatten</DemeanorCfg>, and off|on for string, constant and resource encryption, call hiding, anti-tamper, anti-debug, enum deletion and each kind of symbol renaming. Each is empty by default, meaning the strongest level. Regex exclusions take their pattern from <Pattern> metadata: <DemeanorExcludeRegex Include="dto-types"><Pattern>^MyApp\.Dto\..*$</Pattern></DemeanorExcludeRegex>. MSBuild reads an item's Include as a file specification, so a regex belongs in metadata, where it reaches the obfuscator exactly as written; DEM0001 reports a pattern placed in Include. Project rules and resolved decisions live in a .demeanor directory beside the project and travel with the repository; <DemeanorFailOnPendingDecisions> turns an unresolved decision into a build failure. Compiled XAML (BAML) tracks renamed types, including plain CLR classes used from markup. An expired Enterprise licence fails the build rather than producing a partially protected assembly. The obfuscator ships inside the package for Windows x64 and Linux x64. Pricing and purchase: https://www.wiseowlsoftware.com/pricing.