<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: dotnet</title>
    <description>The latest articles tagged 'dotnet' on DEV Community.</description>
    <link>https://dev.to/t/dotnet</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tag/dotnet"/>
    <language>en</language>
    <item>
      <title>Merge and Combine PowerPoint PPT/PPTX Presentations in C#</title>
      <dc:creator>Muhammad Mustafa</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:45:36 +0000</pubDate>
      <link>https://dev.to/groupdocs-cloud/merge-and-combine-powerpoint-pptpptx-presentations-in-c-4k37</link>
      <guid>https://dev.to/groupdocs-cloud/merge-and-combine-powerpoint-pptpptx-presentations-in-c-4k37</guid>
      <description>&lt;p&gt;Tired of manually stitching together dozens of PowerPoint decks? In C# you can automate the whole process and output a single, polished presentation in seconds. This guide walks you through calling the &lt;strong&gt;GroupDocs Cloud REST API&lt;/strong&gt; from a .NET app, covering setup, authentication, and the exact request payload needed to merge whole files or selected slides.&lt;/p&gt;

&lt;p&gt;You’ll see step‑by‑step code snippets that download, combine, and save PPT or PPTX files, plus tips for handling slide ordering and preserving formatting. Whether you need to merge full presentations or cherry‑pick specific slides, the example projects give you a reusable pattern for any automation pipeline.&lt;/p&gt;

&lt;p&gt;Integrate this solution into your CI/CD workflow and keep your decks up to date automatically.&lt;/p&gt;

&lt;p&gt;Read the full guide → &lt;a href="https://blog.groupdocs.cloud/merger/merge-powerpoint-pptpptx-files-online-using-rest-api-in-csharp/?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=blogcaster" rel="noopener noreferrer"&gt;https://blog.groupdocs.cloud/merger/merge-powerpoint-pptpptx-files-online-using-rest-api-in-csharp/?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=blogcaster&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hardcoded strings are leaking your .NET app’s secrets</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:20:55 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/hardcoded-strings-are-leaking-your-net-apps-secrets-1dnj</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/hardcoded-strings-are-leaking-your-net-apps-secrets-1dnj</guid>
      <description>&lt;p&gt;Open any .NET binary in a decompiler and one of the first things you'll see is a clean list of every string literal in the app. For most applications, that list is a roadmap to how everything works — and sometimes to things that were never meant to be seen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why plain-text strings are a problem
&lt;/h2&gt;

&lt;p&gt;String literals compile straight into your assembly's metadata, completely readable. From that list an attacker can immediately learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API endpoints and URLs&lt;/strong&gt; your app talks to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error and log messages&lt;/strong&gt; that reveal internal logic and control flow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Registry keys, file paths, and feature flags.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded secrets&lt;/strong&gt; that shouldn't be there at all — API keys, tokens, connection strings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even without decompiling a single method, searching the string table often tells an attacker exactly where to look next — for example, jumping straight to your licensing code by searching for "license" or "trial".&lt;/p&gt;

&lt;h2&gt;
  
  
  What string encryption does
&lt;/h2&gt;

&lt;p&gt;String encryption replaces those readable literals with encrypted data that's decrypted at runtime:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each literal is encrypted at build time, ideally with a &lt;strong&gt;fresh per-build key&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The plain text no longer appears in the binary's string table.&lt;/li&gt;
&lt;li&gt;At runtime, an inlined routine decrypts the value on demand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Done well, the decryptor is &lt;strong&gt;unbranded&lt;/strong&gt; (its name doesn't advertise which tool produced it) and inlined, so it's not a single obvious function an attacker can hook to dump every string at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't do
&lt;/h2&gt;

&lt;p&gt;String encryption raises the bar; it isn't a vault. A determined attacker can still run the app and recover decrypted strings from memory. So the rule stands: &lt;strong&gt;don't ship real secrets in the client at all.&lt;/strong&gt; Keep private keys and master credentials server-side. String encryption protects your &lt;em&gt;code's&lt;/em&gt; strings — endpoints, messages, logic markers — not secrets that should never leave your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it fits
&lt;/h2&gt;

&lt;p&gt;String encryption is one layer of a hardened build, alongside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identifier renaming&lt;/strong&gt; — removes readable names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control-flow flattening&lt;/strong&gt; — hides logic structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-tamper / anti-debug&lt;/strong&gt; — stops live patching and stepping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt; encrypts string literals with a per-build key and an unbranded, inlined decryptor, as part of the same pass that renames and flattens your code — across .NET Framework 4.8 and .NET 6–10. See it on your own binary with the &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;free edition&lt;/a&gt;: decompile before and after, and watch the string table go dark.&lt;/p&gt;

</description>
      <category>explainer</category>
      <category>dotnet</category>
      <category>security</category>
    </item>
    <item>
      <title>Adding licensing to your .NET app? Protect the license check too</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:20:40 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/adding-licensing-to-your-net-app-protect-the-license-check-too-1k13</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/adding-licensing-to-your-net-app-protect-the-license-check-too-1k13</guid>
      <description>&lt;p&gt;Adding licensing to a .NET application is straightforward. Making that licensing &lt;em&gt;hard to bypass&lt;/em&gt; is the part most developers underestimate. This post covers both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common .NET licensing approaches
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offline signed license files/keys.&lt;/strong&gt; You sign a license (e.g. with RSA) and the app verifies it against an embedded public key. Simple, works offline, but can't be revoked once issued.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Online activation.&lt;/strong&gt; The app contacts a server to activate a key, binding it to a machine and enforcing a seat limit. Supports revocation and subscriptions; needs a backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node-locking.&lt;/strong&gt; Tie a license to a hardware/machine fingerprint so a key can't be freely shared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature gating.&lt;/strong&gt; Unlock "pro" features based on the license tier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these are good patterns. But they share one weakness.&lt;/p&gt;

&lt;h2&gt;
  
  
  The weak point: the check itself
&lt;/h2&gt;

&lt;p&gt;Every one of these approaches eventually runs code like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;license&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;EnableProFeatures&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In an unprotected .NET assembly, that check is trivial to defeat. An attacker opens your binary in &lt;strong&gt;dnSpy&lt;/strong&gt;, finds the method, edits the IL so &lt;code&gt;IsValid&lt;/code&gt; always returns &lt;code&gt;true&lt;/code&gt; (or removes the check entirely), and saves a patched build. Your carefully signed, node-locked, online-activated license — bypassed in minutes, because the &lt;em&gt;verification code&lt;/em&gt; was readable and editable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually makes licensing hold
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Obfuscation&lt;/strong&gt; — rename and flatten the license logic so it's hard to locate and understand in a decompiler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String encryption&lt;/strong&gt; — hide the URLs, keys, and messages that make the licensing code easy to search for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-tamper&lt;/strong&gt; — detect that the assembly was modified after signing, so a patched binary refuses to run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-debug&lt;/strong&gt; — detect an attached debugger like dnSpy so attackers can't step through and edit the check live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: your licensing design provides the &lt;em&gt;policy&lt;/em&gt;; obfuscation and hardening protect its &lt;em&gt;enforcement&lt;/em&gt;. Skip the second half and the first is decorative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Choose a licensing model (offline signed, or online activation with revocation and seats).&lt;/li&gt;
&lt;li&gt;Keep any real secrets — signing keys, server credentials — off the client.&lt;/li&gt;
&lt;li&gt;Obfuscate and harden the Release build, including the licensing code, with anti-tamper enabled.&lt;/li&gt;
&lt;li&gt;Verify the protected build still activates and runs identically.&lt;/li&gt;
&lt;li&gt;Sign the binary so tampering is detectable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt; handles step 3–5 — obfuscation, string encryption, anti-tamper/anti-debug, and Authenticode signing — for .NET Framework 4.8 and .NET 6–10. See &lt;a href="https://delta1labs.com/docs/nebula/how-it-works" rel="noopener noreferrer"&gt;how it works&lt;/a&gt;, and note how the same techniques that hide your algorithms also protect your license enforcement.&lt;/p&gt;

&lt;p&gt;Start free from the &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;download page&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>guide</category>
      <category>dotnet</category>
      <category>licensing</category>
    </item>
    <item>
      <title>Can someone decompile my .NET app? Stopping dnSpy and ILSpy</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:15:59 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/can-someone-decompile-my-net-app-stopping-dnspy-and-ilspy-2k43</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/can-someone-decompile-my-net-app-stopping-dnspy-and-ilspy-2k43</guid>
      <description>&lt;p&gt;If you've ever wondered whether someone can decompile your .NET app: they can, easily, with free tools. Here's how it works and what to do about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How decompilation works
&lt;/h2&gt;

&lt;p&gt;.NET compiles to &lt;strong&gt;IL&lt;/strong&gt;, which preserves names and structure. Decompilers reverse that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ILSpy / dotPeek&lt;/strong&gt; — open a &lt;code&gt;.dll&lt;/code&gt;/&lt;code&gt;.exe&lt;/code&gt; and show reconstructed C#.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dnSpy&lt;/strong&gt; — goes further: it decompiles &lt;em&gt;and&lt;/em&gt; lets an attacker set breakpoints, edit IL, and patch your assembly live. It's a favorite for defeating naive license checks — find the &lt;code&gt;if (isLicensed)&lt;/code&gt;, flip it, save.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Out of the box, none of this requires skill. That's the problem obfuscation and hardening solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making your assembly hard to read
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identifier renaming&lt;/strong&gt; strips the readable names dnSpy/ILSpy display.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control-flow flattening&lt;/strong&gt; turns clean methods into dispatcher state machines, so the decompiled output no longer resembles your logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String encryption&lt;/strong&gt; removes the literal strings that make code easy to navigate and search.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Making your assembly hard to debug and patch
&lt;/h2&gt;

&lt;p&gt;Reading is only half of it — dnSpy's real power is &lt;em&gt;interactive&lt;/em&gt; tampering. To counter that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Anti-debug&lt;/strong&gt; detects when a debugger like dnSpy is attached and lets you react (exit, throw, or a custom response).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-tamper&lt;/strong&gt; detects when your assembly has been modified after signing, so a patched binary can refuse to run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together these stop the "attach dnSpy, patch the check, save" attack that trivially defeats unprotected apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  A word on license checks specifically
&lt;/h2&gt;

&lt;p&gt;If your app has any licensing or "pro feature" gating, the check itself is the target. An unprotected &lt;code&gt;if (license.IsValid)&lt;/code&gt; is one dnSpy edit away from being bypassed. Obfuscating the check and adding anti-tamper is what makes it hold up. (More on this in &lt;a href="https://delta1labs.com/blog/protect-dotnet-licensing-checks/" rel="noopener noreferrer"&gt;protecting .NET license checks&lt;/a&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;The practical answer to "can someone decompile my .NET app?" is: yes by default, but you can make it far more trouble than it's worth. Obfuscate and harden your Release build, verify it still runs identically, sign it, and ship.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt; provides renaming, control-flow flattening, string encryption, and anti-tamper/anti-debug across .NET Framework 4.8 and .NET 6–10 — try the &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;free edition&lt;/a&gt; and open the result in ILSpy to see the difference yourself. Weighing your options first? Compare the &lt;a href="https://delta1labs.com/blog/best-dotnet-obfuscators-2026/" rel="noopener noreferrer"&gt;best .NET obfuscators of 2026&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>explainer</category>
      <category>dotnet</category>
      <category>security</category>
    </item>
    <item>
      <title>How to obfuscate a WPF app without breaking XAML data binding</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:15:40 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/how-to-obfuscate-a-wpf-app-without-breaking-xaml-data-binding-2hpd</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/how-to-obfuscate-a-wpf-app-without-breaking-xaml-data-binding-2hpd</guid>
      <description>&lt;p&gt;WPF apps are a common obfuscation target — they ship to end users' machines, so the IL is right there to decompile. The one thing to get right is that &lt;strong&gt;XAML binds to your view-models by name at runtime&lt;/strong&gt;, so those names have to survive. Here's the whole process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why WPF needs a little care
&lt;/h2&gt;

&lt;p&gt;When you write &lt;code&gt;{Binding CustomerName}&lt;/code&gt; or &lt;code&gt;Command="{Binding SaveCommand}"&lt;/code&gt;, WPF resolves &lt;code&gt;CustomerName&lt;/code&gt; and &lt;code&gt;SaveCommand&lt;/code&gt; &lt;strong&gt;by name&lt;/strong&gt; at runtime via reflection. If obfuscation renames those properties to &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, the binding silently fails — you get a blank field or a dead button, with a binding error in the debug output.&lt;/p&gt;

&lt;p&gt;Everything &lt;em&gt;else&lt;/em&gt; — your business logic, algorithms, services — has no such constraint and can be fully renamed, flattened and encrypted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — preserve what XAML binds to
&lt;/h2&gt;

&lt;p&gt;The simplest, safest setting for a WPF app is &lt;strong&gt;preserve public API&lt;/strong&gt;, because bound view-model members are usually public:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bin/Release/net8.0/MyApp.dll"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputDirectory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"preservePublicApi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"controlFlowObfuscation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"encryptStrings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a bound member isn't public, exclude the view-model explicitly instead of leaving names exposed everywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"MyApp.ViewModels.MainViewModel"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nebula also &lt;strong&gt;auto-detects&lt;/strong&gt; most reflection and serialization usage, so converters and types referenced with &lt;code&gt;{x:Type}&lt;/code&gt; are generally preserved for you. See &lt;a href="https://delta1labs.com/docs/nebula/keeping-your-app-working/" rel="noopener noreferrer"&gt;Keeping your app working&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — obfuscate the internals hard
&lt;/h2&gt;

&lt;p&gt;Your public view-model surface stays named, but the code behind it is where the value is — so lean on control flow and string encryption there. With &lt;code&gt;preservePublicApi&lt;/code&gt; on, private and internal members are still renamed, and control-flow flattening applies everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — run it and click through
&lt;/h2&gt;

&lt;p&gt;This is the real test. Obfuscate, launch the protected build, and exercise the screens — especially anything data-bound. If a field is blank or a command is dead, check the debug output for a binding error naming the member, then add that member (or its view-model) to &lt;code&gt;exclude&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — sign it for distribution
&lt;/h2&gt;

&lt;p&gt;Desktop users will hit a "Windows protected your PC / Unknown publisher" prompt on an unsigned installer. Sign the protected output with your Authenticode certificate (Nebula can apply it as part of the run) or distribute through the Microsoft Store. See &lt;a href="https://delta1labs.com/docs/nebula/app-types/#wpf--winforms-desktop-xaml" rel="noopener noreferrer"&gt;Protecting different project types&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep &lt;code&gt;preservePublicApi&lt;/code&gt; on so bound members survive.&lt;/li&gt;
&lt;li&gt;Exclude any non-public view-model that XAML binds to.&lt;/li&gt;
&lt;li&gt;Let control-flow + string encryption protect the internals.&lt;/li&gt;
&lt;li&gt;Run the app and click through the bound screens as your acceptance test.&lt;/li&gt;
&lt;li&gt;Sign the result before you ship it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready to try it? &lt;a href="https://delta1labs.com/download?product=nebula" rel="noopener noreferrer"&gt;Download Nebula.NET free&lt;/a&gt; and protect your first WPF build in a few minutes.&lt;/p&gt;

</description>
      <category>guide</category>
      <category>dotnet</category>
      <category>wpf</category>
      <category>obfuscation</category>
    </item>
    <item>
      <title>Obfuscate only on your build server (keep developer builds clean)</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:15:28 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/obfuscate-only-on-your-build-server-keep-developer-builds-clean-23hk</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/obfuscate-only-on-your-build-server-keep-developer-builds-clean-23hk</guid>
      <description>&lt;p&gt;Obfuscation is great for what you &lt;em&gt;ship&lt;/em&gt; and a nuisance for what you &lt;em&gt;debug&lt;/em&gt;. The best-practice setup is: &lt;strong&gt;developers build normally (unobfuscated, debuggable), and only the build server that produces your official packages applies protection&lt;/strong&gt; — same source, same &lt;code&gt;dotnet build&lt;/code&gt;, no code changes. Here's how to set that up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;Nebula obfuscates your compiled output, not your source, and it's driven by configuration — so whether protection runs comes down to a single switch that exists &lt;strong&gt;only on the build agent&lt;/strong&gt;. Developer machines don't have that switch, so their builds are untouched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option A — the MSBuild task, gated by an environment variable
&lt;/h2&gt;

&lt;p&gt;Nebula's build target only runs when the &lt;code&gt;NebulaObfuscate&lt;/code&gt; property is &lt;code&gt;true&lt;/code&gt;, and MSBuild reads that from the environment. On the build agent, set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;NebulaObfuscate&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;NEBULA_LICENSE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;your build-server license key&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every build on that agent is protected after compile; developer machines (variable absent) build exactly as before. Nothing changes in your &lt;code&gt;.csproj&lt;/code&gt; behaviour on a dev box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option B — zero package reference (fully dependency-free)
&lt;/h2&gt;

&lt;p&gt;If you don't want any Nebula reference in your projects at all, invoke the CLI from a repo-level &lt;code&gt;Directory.Build.targets&lt;/code&gt;, gated by your own variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Target&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"NebulaObfuscate"&lt;/span&gt; &lt;span class="na"&gt;AfterTargets=&lt;/span&gt;&lt;span class="s"&gt;"Build"&lt;/span&gt; &lt;span class="na"&gt;Condition=&lt;/span&gt;&lt;span class="s"&gt;"'$(NEBULA_OBFUSCATE)' == '1'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class="na"&gt;Command=&lt;/span&gt;&lt;span class="s"&gt;"nebula --config &amp;amp;quot;$(MSBuildProjectDirectory)/nebula.config.json&amp;amp;quot; --output &amp;amp;quot;$(TargetDir)obf&amp;amp;quot;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set &lt;code&gt;NEBULA_OBFUSCATE=1&lt;/code&gt; (and &lt;code&gt;NEBULA_LICENSE=…&lt;/code&gt;) on the agent and install the CLI. Developer boxes skip the step entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting the variable on the agent
&lt;/h2&gt;

&lt;p&gt;Set it once, as the account your builds run under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Windows agent, machine-wide (run as Administrator):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NEBULA_OBFUSCATE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Machine'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NEBULA_LICENSE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'LIC-XXXX-XXXX-XXXX'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Machine'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Linux/macOS agent (service environment or profile):&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NEBULA_OBFUSCATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NEBULA_LICENSE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;LIC-XXXX-XXXX-XXXX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most CI systems also let you define these as pipeline/agent variables in their UI — set them on the agent, never in the repo. Full cmd/PowerShell/bash steps are in &lt;a href="https://delta1labs.com/docs/nebula/msbuild/#setting-the-variables-on-the-build-agent" rel="noopener noreferrer"&gt;MSBuild &amp;amp; CI&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  You only license the build machine
&lt;/h2&gt;

&lt;p&gt;Because protection happens on the build server, only the &lt;strong&gt;build machine(s)&lt;/strong&gt; need a license — not every developer. Activate on the agent and you're done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify
&lt;/h2&gt;

&lt;p&gt;Build on a dev box: output is normal and debuggable. Build on the agent: the output is renamed, flattened and encrypted, and your pipeline archives the protected artifact. Same commit, two very different binaries — exactly what you want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://delta1labs.com/download?product=nebula" rel="noopener noreferrer"&gt;Download Nebula.NET free&lt;/a&gt; to try it, and see the full build guide in the &lt;a href="https://delta1labs.com/docs/nebula/msbuild/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>guide</category>
      <category>dotnet</category>
      <category>ci</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to obfuscate a NuGet package before you publish it</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:15:18 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/how-to-obfuscate-a-nuget-package-before-you-publish-it-6hb</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/how-to-obfuscate-a-nuget-package-before-you-publish-it-6hb</guid>
      <description>&lt;p&gt;If you distribute a commercial .NET library on NuGet, anyone who installs it can open your DLL in a decompiler and read your implementation. You can protect it — the trick is protecting the &lt;strong&gt;internals&lt;/strong&gt; while keeping the &lt;strong&gt;public API&lt;/strong&gt; your consumers call intact. Nebula handles the whole package for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one rule: keep your public API
&lt;/h2&gt;

&lt;p&gt;Consumers reference your library by its public types and members. If obfuscation renamed those, their code wouldn't compile against your package. So for a library the golden setting is &lt;strong&gt;preserve public API&lt;/strong&gt; — public/protected names stay, everything internal is renamed, flattened and encrypted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — point Nebula at the package
&lt;/h2&gt;

&lt;p&gt;You don't have to unpack anything. Give Nebula the &lt;code&gt;.nupkg&lt;/code&gt; directly and it obfuscates the assemblies inside and repacks a protected package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bin/Release/MyLib.1.2.3.nupkg"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputDirectory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"preservePublicApi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"controlFlowObfuscation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"encryptStrings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nebula &lt;span class="nt"&gt;--config&lt;/span&gt; nebula.config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The protected &lt;code&gt;MyLib.1.2.3.nupkg&lt;/code&gt; lands in &lt;code&gt;protected/&lt;/code&gt;, ready to push.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — if you ship multiple libraries
&lt;/h2&gt;

&lt;p&gt;Products often span several packages that call each other's public members. If you want to rename across them, obfuscate them &lt;strong&gt;together&lt;/strong&gt; so the cross-references are rewritten consistently — otherwise renaming a public member in one breaks the others. Add all the assemblies to &lt;code&gt;inputs&lt;/code&gt; and enable &lt;code&gt;crossAssemblyRename&lt;/code&gt;. See &lt;a href="https://delta1labs.com/docs/nebula/multi-assembly/" rel="noopener noreferrer"&gt;Multiple assemblies&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — mind reflection and serialization
&lt;/h2&gt;

&lt;p&gt;Auto-detect preserves types and members referenced by reflection or carrying serialization attributes (&lt;code&gt;System.Text.Json&lt;/code&gt;, &lt;code&gt;Newtonsoft&lt;/code&gt;, &lt;code&gt;DataContract&lt;/code&gt;, XML). If your library exposes DTOs that consumers serialize, keep those attributes (or exclude the DTOs) so the wire format doesn't change. See &lt;a href="https://delta1labs.com/docs/nebula/keeping-your-app-working/" rel="noopener noreferrer"&gt;Keeping your app working&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — sign and verify
&lt;/h2&gt;

&lt;p&gt;Strong-name signing must be re-applied after obfuscation — set &lt;code&gt;strongNameKeyFile&lt;/code&gt; and Nebula signs the protected output. Then install the protected package into a throwaway consumer project and run your tests against it: the public API compiles and behaves exactly as before, but the internals are now hard to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automate it in your release pipeline
&lt;/h2&gt;

&lt;p&gt;Wire this into CI so every published package is protected, without touching your source. See &lt;a href="https://delta1labs.com/docs/nebula/msbuild/" rel="noopener noreferrer"&gt;MSBuild &amp;amp; CI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://delta1labs.com/download?product=nebula" rel="noopener noreferrer"&gt;Download Nebula.NET free&lt;/a&gt; and protect your next NuGet release.&lt;/p&gt;

</description>
      <category>guide</category>
      <category>dotnet</category>
      <category>nuget</category>
      <category>obfuscation</category>
    </item>
    <item>
      <title>A .NET Reactor alternative in 2026</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:15:04 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/a-net-reactor-alternative-in-2026-3d39</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/a-net-reactor-alternative-in-2026-3d39</guid>
      <description>&lt;p&gt;.NET Reactor, by Eziriz, is one of the most popular commercial .NET obfuscators — and for good reason. It's affordable, it's been around a long time, and it packs a lot into one tool. If you're comparing it with &lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt;, here's a straight, fair breakdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where .NET Reactor is strong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price.&lt;/strong&gt; A one-time perpetual license at a genuinely accessible price point — a big part of its popularity with indies and small studios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NecroBit.&lt;/strong&gt; Its headline feature compiles IL to native code, so those methods can't be decompiled back to C# by ordinary tools. That's real protection for sensitive logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in licensing.&lt;/strong&gt; A full license-key system — trials, expiry, hardware locking — bundled in. If you need that in one box, it's convenient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The usual suite&lt;/strong&gt; — string/resource encryption, anti-tamper, anti-debug, control-flow obfuscation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a lot of value. We're not here to pretend otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Nebula.NET differs
&lt;/h2&gt;

&lt;p&gt;Nebula approaches the same problem — "make my shipped code not worth reverse-engineering" — with some different bets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code virtualization instead of native compilation.&lt;/strong&gt; Nebula's Enterprise &lt;a href="https://delta1labs.com/articles/code-virtualization" rel="noopener noreferrer"&gt;virtualization&lt;/a&gt; turns a method's IL into a custom bytecode run by an embedded VM. Native code (like NecroBit's output) has mature disassemblers and decompilers; a &lt;em&gt;custom&lt;/em&gt; VM has none until an attacker builds one — for your specific build. Both remove readable IL; the VM route raises the reverse-engineering cost differently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verified de4dot resistance.&lt;/strong&gt; Nebula's control flow and per-call-site string encryption are engineered — and tested against the real de4dot — to &lt;a href="https://delta1labs.com/articles/beating-de4dot" rel="noopener noreferrer"&gt;survive automated deobfuscation&lt;/a&gt;. We show the result rather than asserting it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A genuine free edition + a free decompiler to check.&lt;/strong&gt; Try Nebula on your own assembly for free, then open the output in &lt;a href="https://delta1labs.com/products/glass" rel="noopener noreferrer"&gt;Glass.NET&lt;/a&gt; and see exactly what a would-be attacker would. Being able to &lt;em&gt;verify&lt;/em&gt; protection is underrated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern targets.&lt;/strong&gt; Dedicated &lt;a href="https://delta1labs.com/blog/protect-blazor-webassembly-from-decompilation/" rel="noopener noreferrer"&gt;Blazor WebAssembly protection&lt;/a&gt; — the most exposed .NET target — plus .NET Framework 4.8 through .NET 6–10.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow.&lt;/strong&gt; CLI, desktop GUI, and MSBuild/CI, with &lt;a href="https://delta1labs.com/docs/nebula/deobfuscation/" rel="noopener noreferrer"&gt;stack-trace de-obfuscation&lt;/a&gt; so your production crash reports stay readable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where .NET Reactor may still win for you
&lt;/h2&gt;

&lt;p&gt;If a &lt;strong&gt;built-in licensing system&lt;/strong&gt; is a hard requirement and you want it bundled with the obfuscator, .NET Reactor delivers that in one purchase — Nebula focuses on code protection and pairs with online activation rather than shipping a full key generator. And if native compilation specifically is what you want, NecroBit is its purpose-built feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to decide
&lt;/h2&gt;

&lt;p&gt;Don't decide on a feature list — decide on &lt;em&gt;your&lt;/em&gt; binary. Protect a representative assembly with each, run your test suite against the output to confirm it still behaves identically, then try to read the protected build in a decompiler. &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;Download Nebula.NET free&lt;/a&gt; and put it head-to-head; the one whose output you can't make sense of wins.&lt;/p&gt;

</description>
      <category>comparison</category>
      <category>dotnet</category>
      <category>obfuscation</category>
    </item>
    <item>
      <title>How to obfuscate a .NET assembly (step-by-step, 2026)</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:14:24 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/how-to-obfuscate-a-net-assembly-step-by-step-2026-28ab</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/how-to-obfuscate-a-net-assembly-step-by-step-2026-28ab</guid>
      <description>&lt;p&gt;.NET assemblies are easy to decompile. Tools like ILSpy, dnSpy and dotPeek can turn your compiled DLL back into near-original C# in seconds, exposing your algorithms, license checks, API keys and business logic. Obfuscation raises the cost of that by rewriting the compiled IL so it's hard to read — without changing how your program runs.&lt;/p&gt;

&lt;p&gt;This guide walks through obfuscating a .NET assembly the right way, using &lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you start
&lt;/h2&gt;

&lt;p&gt;Obfuscate your &lt;strong&gt;release build&lt;/strong&gt;, not debug, and keep a copy of the original. Decide what must keep its public names — for libraries and plugins, your public API and any members hit by reflection or serialization should be preserved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Install the tool
&lt;/h2&gt;

&lt;p&gt;Download the Windows installer from the &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;download page&lt;/a&gt; and run it. It installs both a command-line tool (&lt;code&gt;nebula&lt;/code&gt;) and a desktop GUI. No .NET runtime is required on the machine running it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Create a configuration
&lt;/h2&gt;

&lt;p&gt;Nebula is driven by a small JSON file. Create &lt;code&gt;nebula.config.json&lt;/code&gt; next to your build output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schemaVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bin/Release/net8.0/MyApp.dll"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputDirectory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"preservePublicApi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"encryptStrings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"controlFlowObfuscation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;preservePublicApi&lt;/strong&gt; keeps public types/members named — essential for libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;encryptStrings&lt;/strong&gt; encrypts literal strings so keys and messages don't sit in plain text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;controlFlowObfuscation&lt;/strong&gt; rewrites your methods so the original logic is obscured.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3 — Run it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nebula &lt;span class="nt"&gt;--config&lt;/span&gt; nebula.config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see a summary of what was renamed, flattened and encrypted, and a protected copy of your assembly appears in &lt;code&gt;protected/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Verify it still works
&lt;/h2&gt;

&lt;p&gt;This is the step most people skip — and it's the most important. Obfuscation must never change behavior. Run your app or your full test suite against the protected build and confirm everything behaves exactly as before. Nebula validates output automatically and is tested to preserve runtime behavior across .NET Framework 4.8 and .NET 6–10, but you should always run your own tests too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What each transform does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identifier renaming&lt;/strong&gt; replaces meaningful type/method/field names with meaningless ones, while preserving anything that must keep its name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control-flow flattening&lt;/strong&gt; rewrites methods into dispatcher-driven state machines, so a decompiler can't show your original structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String encryption&lt;/strong&gt; encrypts literals with a per-build key, decrypted at runtime by an inlined routine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-tamper and anti-debug&lt;/strong&gt; detect a modified assembly or an attached debugger and react as you configure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more in &lt;a href="https://delta1labs.com/docs/nebula/how-it-works" rel="noopener noreferrer"&gt;how it works&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch out for reflection and serialization
&lt;/h2&gt;

&lt;p&gt;If your code looks up types or members by string name (reflection, dependency injection, JSON/XML serialization, some ORMs), renaming those members will break it. Preserve them with &lt;code&gt;preservePublicApi&lt;/code&gt; and Nebula's include/exclude rules. When something misbehaves after obfuscation, this is almost always the cause — narrow down which transform is involved and exclude the affected members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automate it in CI
&lt;/h2&gt;

&lt;p&gt;Once it works locally, protect on every build. Nebula returns meaningful exit codes and takes a &lt;code&gt;--json&lt;/code&gt; summary, so it drops into any pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nebula &lt;span class="nt"&gt;--config&lt;/span&gt; nebula.config.json &lt;span class="nt"&gt;--json&lt;/span&gt; nebula-summary.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://delta1labs.com/docs/nebula/msbuild" rel="noopener noreferrer"&gt;MSBuild &amp;amp; CI&lt;/a&gt; for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To obfuscate a .NET assembly: install a tool, write a config that preserves your public API, enable the transforms you need, run it, and — crucially — verify your app still runs identically. Start with the &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;free edition&lt;/a&gt;; it's enough to protect small projects and evaluate the full suite.&lt;/p&gt;

</description>
      <category>guide</category>
      <category>dotnet</category>
      <category>obfuscation</category>
    </item>
    <item>
      <title>An Eazfuscator.NET alternative in 2026</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:13:37 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/an-eazfuscatornet-alternative-in-2026-1idi</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/an-eazfuscatornet-alternative-in-2026-1idi</guid>
      <description>&lt;p&gt;Eazfuscator.NET, by Gapotchenko, is a well-regarded .NET obfuscator with a reputation for a clean developer experience and responsive support. If it's on your shortlist alongside &lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt;, here's an honest side-by-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Eazfuscator.NET is strong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MSBuild-native by design.&lt;/strong&gt; It hooks into the build so protection happens automatically on every compile — very little ceremony. That "set it and forget it" integration is a genuine strength.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code virtualization.&lt;/strong&gt; It offers virtualization of sensitive methods, not just renaming and flattening.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polished and supported.&lt;/strong&gt; A mature tool with stack-trace decoding and a good reputation for support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a solid, respected product. Our aim here is a fair comparison, not a takedown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Nebula.NET differs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A genuine free edition.&lt;/strong&gt; Eazfuscator is paid-only (with a trial). Nebula's &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;free edition&lt;/a&gt; does real work — renaming with public-API preservation, plus string encryption and control flow — so you can protect a small project or fully evaluate before spending anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparent per-seat pricing&lt;/strong&gt; on the &lt;a href="https://delta1labs.com/pricing" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;, with a perpetual option — no subscription-only lock-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A desktop GUI &lt;em&gt;and&lt;/em&gt; CLI &lt;em&gt;and&lt;/em&gt; MSBuild.&lt;/strong&gt; If you like Eazfuscator's build integration, Nebula matches it — and adds a GUI for one-off jobs, exploring settings, and onboarding teammates who don't live in the build scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verified de4dot resistance.&lt;/strong&gt; Nebula's control flow and per-call-site string encryption are tested against the real de4dot to &lt;a href="https://delta1labs.com/articles/beating-de4dot" rel="noopener noreferrer"&gt;survive automated deobfuscation&lt;/a&gt; — with the result shown, not just claimed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern targets.&lt;/strong&gt; Dedicated &lt;a href="https://delta1labs.com/blog/protect-blazor-webassembly-from-decompilation/" rel="noopener noreferrer"&gt;Blazor WebAssembly protection&lt;/a&gt; for the most-exposed .NET deployment, plus .NET Framework 4.8 through .NET 6–10.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the output.&lt;/strong&gt; Protect a build, then open it in the free &lt;a href="https://delta1labs.com/products/glass" rel="noopener noreferrer"&gt;Glass.NET&lt;/a&gt; decompiler and see exactly what's exposed — a check most vendors don't hand you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both tools offer &lt;a href="https://delta1labs.com/articles/code-virtualization" rel="noopener noreferrer"&gt;code virtualization&lt;/a&gt; and stack-trace de-obfuscation, so on those the decision comes down to workflow, pricing model, and the ability to try before you buy.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose
&lt;/h2&gt;

&lt;p&gt;If deep, zero-config MSBuild integration and an established support relationship are your top priorities, Eazfuscator.NET earns its reputation. If you want to start free, see transparent pricing, get a GUI alongside the build integration, and protect modern targets like Blazor WASM — evaluate Nebula.NET directly.&lt;/p&gt;

&lt;p&gt;As always, decide on your own binary: protect a representative assembly with each, run your tests against the output, and try to read it back in a decompiler. &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;Download Nebula.NET free&lt;/a&gt; and compare.&lt;/p&gt;

</description>
      <category>comparison</category>
      <category>dotnet</category>
      <category>obfuscation</category>
    </item>
    <item>
      <title>A Dotfuscator alternative for .NET in 2026</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:13:15 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/a-dotfuscator-alternative-for-net-in-2026-dp</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/a-dotfuscator-alternative-for-net-in-2026-dp</guid>
      <description>&lt;p&gt;Dotfuscator, from PreEmptive, is the grandparent of .NET obfuscators — it's been protecting managed code since the early .NET Framework days and has a deep enterprise track record. If you're evaluating it in 2026, here's a fair look at where it fits and where a more modern, transparently-priced tool like &lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt; might serve you better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Dotfuscator is strong
&lt;/h2&gt;

&lt;p&gt;Credit where it's due. Dotfuscator has years of enterprise deployment behind it, PreEmptive's runtime tamper/shelf-life checks and application analytics, and the convenience of a Community Edition bundled right inside Visual Studio. For large organizations already standardized on it, that maturity and support relationship are real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where teams run into friction
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quote-based pricing.&lt;/strong&gt; Dotfuscator Professional isn't publicly priced — you request a quote, and it's positioned for enterprise budgets. For an indie, a startup, or a small ISV, that alone is often a non-starter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The free edition is very limited.&lt;/strong&gt; The Visual Studio Community Edition does basic renaming only — not the control flow, string encryption, or tamper protection that actually resist reverse engineering. So "free" here doesn't mean "protected."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise-shaped workflow.&lt;/strong&gt; The tooling and licensing are built around large-team procurement, which can feel heavy if you just want to protect a build and ship.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Nebula.NET compares
&lt;/h2&gt;

&lt;p&gt;Nebula.NET is a modern, actively-developed suite built for the same job with a different posture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A genuine free edition&lt;/strong&gt; — real renaming, plus a taste of string encryption and control flow — not just a rename-only stub. Try it on your own assembly before you pay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparent per-seat pricing&lt;/strong&gt; — see it on the &lt;a href="https://delta1labs.com/pricing" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;; no quote process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The full protection ladder&lt;/strong&gt; — identifier renaming (public-API preserving), control-flow flattening, string encryption, anti-tamper/anti-debug, resource and metadata hardening, and Authenticode signing, via CLI, desktop GUI, and MSBuild/CI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern protections Dotfuscator's lineage predates&lt;/strong&gt; — Enterprise &lt;a href="https://delta1labs.com/articles/code-virtualization" rel="noopener noreferrer"&gt;code virtualization&lt;/a&gt; (methods compiled to a custom bytecode VM, so there's no IL to read), dedicated &lt;a href="https://delta1labs.com/blog/protect-blazor-webassembly-from-decompilation/" rel="noopener noreferrer"&gt;Blazor WebAssembly protection&lt;/a&gt;, and control flow specifically engineered to &lt;a href="https://delta1labs.com/articles/beating-de4dot" rel="noopener noreferrer"&gt;survive automated deobfuscators like de4dot&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify it yourself&lt;/strong&gt; — protect a build, then open it in our free &lt;a href="https://delta1labs.com/products/glass" rel="noopener noreferrer"&gt;Glass.NET&lt;/a&gt; decompiler and see exactly what's exposed. Most vendors don't hand you the tool to check their own output.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Which should you choose?
&lt;/h2&gt;

&lt;p&gt;If you're a large enterprise already invested in PreEmptive's ecosystem and analytics, Dotfuscator's maturity may justify the price. If you want to &lt;em&gt;see the price&lt;/em&gt;, start free, and get modern protections like virtualization and Blazor support without an enterprise procurement cycle, Nebula.NET is worth a direct comparison.&lt;/p&gt;

&lt;p&gt;The honest test is your own binary: protect it with each, then try to read it back in a decompiler. &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;Download Nebula.NET free&lt;/a&gt; and run that test — it takes a few minutes, and it's the only comparison that matters.&lt;/p&gt;

</description>
      <category>comparison</category>
      <category>dotnet</category>
      <category>obfuscation</category>
    </item>
    <item>
      <title>Does obfuscation actually protect .NET code?</title>
      <dc:creator>Zero Heartbeat</dc:creator>
      <pubDate>Thu, 17 Sep 2026 09:13:02 +0000</pubDate>
      <link>https://dev.to/zero_heartbeat_06a3625d7a/does-obfuscation-actually-protect-net-code-4lce</link>
      <guid>https://dev.to/zero_heartbeat_06a3625d7a/does-obfuscation-actually-protect-net-code-4lce</guid>
      <description>&lt;p&gt;Short answer: &lt;strong&gt;yes, but with realistic expectations.&lt;/strong&gt; Obfuscation meaningfully raises the cost and effort of reverse engineering your .NET code — it does not make it mathematically impossible. Understanding that distinction helps you use it well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why .NET code is so exposed
&lt;/h2&gt;

&lt;p&gt;C# and other .NET languages compile to &lt;strong&gt;IL (intermediate language)&lt;/strong&gt;, a high-level bytecode that retains type names, method names, and structure. Free decompilers (ILSpy, dnSpy, dotPeek) reconstruct near-original source from a shipped DLL almost instantly. Without protection, anyone with your binary effectively has your source.&lt;/p&gt;

&lt;h2&gt;
  
  
  What obfuscation actually does
&lt;/h2&gt;

&lt;p&gt;Obfuscation rewrites that IL so it's hard for a human (and a decompiler) to follow, while producing the same runtime behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identifier renaming&lt;/strong&gt; strips the meaningful names decompilers rely on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control-flow flattening&lt;/strong&gt; rewrites methods into dispatcher-driven state machines, hiding the original logic and structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String encryption&lt;/strong&gt; removes readable literals — API endpoints, keys, messages — from the binary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-tamper and anti-debug&lt;/strong&gt; detect a modified assembly or an attached debugger and let you respond.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result: a determined attacker can still analyze your code, but it takes far more time, skill, and motivation — often enough to make it not worth their while.&lt;/p&gt;

&lt;h2&gt;
  
  
  What obfuscation can't do
&lt;/h2&gt;

&lt;p&gt;Be honest with yourself about the limits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's not encryption.&lt;/strong&gt; The code must ultimately run, so a skilled reverse engineer with enough time can still make progress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It won't hide secrets you shouldn't ship.&lt;/strong&gt; Don't embed private keys or master credentials in a client and assume obfuscation makes them safe — it doesn't. Keep true secrets server-side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It doesn't stop copying of the binary.&lt;/strong&gt; That's what licensing and activation are for.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Build layered protection instead
&lt;/h2&gt;

&lt;p&gt;Obfuscation is one layer. Combine it with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Obfuscation + hardening&lt;/strong&gt; — renaming, control flow, string encryption, anti-tamper. (Choosing a tool? See our &lt;a href="https://delta1labs.com/blog/best-dotnet-obfuscators-2026/" rel="noopener noreferrer"&gt;2026 obfuscator comparison&lt;/a&gt;.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Licensing and activation&lt;/strong&gt; — node-locked, seat-enforced keys so a copied binary can't just be reused, and can be revoked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep real secrets off the client&lt;/strong&gt; — put anything that must stay private behind your server/API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code signing&lt;/strong&gt; — so users can verify the binary came from you and wasn't modified.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://delta1labs.com/products/nebula" rel="noopener noreferrer"&gt;Nebula.NET&lt;/a&gt; does the first and fourth, and pairs naturally with online licensing for the second — see &lt;a href="https://delta1labs.com/docs/nebula/how-it-works" rel="noopener noreferrer"&gt;how it works&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Realistic expectations
&lt;/h2&gt;

&lt;p&gt;Think of obfuscation like a good lock: it won't stop every determined attacker forever, but it stops the casual and opportunistic ones, and it buys time against the serious ones. For most commercial .NET software, that shift in cost-to-attack is exactly the point — and it's well worth doing.&lt;/p&gt;

&lt;p&gt;Ready to try it? Grab the &lt;a href="https://delta1labs.com/download" rel="noopener noreferrer"&gt;free edition&lt;/a&gt; and protect an assembly in a few minutes.&lt;/p&gt;

</description>
      <category>explainer</category>
      <category>dotnet</category>
      <category>security</category>
    </item>
  </channel>
</rss>
