Skip to content

Recovering Lost Source Code

Sometimes the source code is gone. The repository was deleted, the developer left, the backup failed. If you still have the compiled .dll or .exe, mcilspy can reconstruct C# source that is often close to the original.

  1. Assess the assembly

    Start with get_assembly_info to check the target framework and whether debug information exists:

    "Get assembly info for LegacyApp.dll"

    If has_debug_info is true, a PDB file may be alongside the assembly. This significantly improves output quality.

  2. Generate a project structure

    Use decompile_assembly with create_project to produce a .csproj file and organized source files:

    "Decompile LegacyApp.dll into a project structure at ./recovered-source"

    The create_project flag tells ILSpy to generate a buildable project rather than a single concatenated output. Combined with nested_directories, source files are organized into namespace-based folder hierarchies.

  3. Enable PDB generation

    Set generate_pdb to produce a portable PDB file alongside the decompiled source. This lets you attach a debugger to the decompiled code:

    "Decompile LegacyApp.dll to ./recovered with create_project, generate_pdb, and nested_directories enabled"
  4. Recover original variable names

    If the assembly ships with its original PDB (or an embedded portable PDB), enable use_pdb_variable_names to replace ILSpy’s generated names (num, text, flag) with the originals:

    "Decompile with use_pdb_variable_names enabled"

    Without this flag, local variables get generic names based on their types. With it, you get connectionTimeout instead of num2.

  5. Build and fix

    The decompiled project usually needs minor adjustments before it compiles. Common issues include missing NuGet package references, unresolved extern methods, and resource files that need regenerating. But the structural recovery is typically complete.

ILSpy decompiles using modern C# syntax by default (Latest). If the original code targeted an older framework, you may want to match the language version for authenticity:

Original FrameworkSuggested Version
.NET Framework 2.0-3.5CSharp3
.NET Framework 4.0CSharp4
.NET Framework 4.5CSharp5
.NET Framework 4.6+CSharp6 or CSharp7
.NET Core 3.xCSharp8_0
.NET 5-6CSharp9_0 or CSharp10_0
.NET 7-8CSharp11_0 or CSharp12_0

Pass the version via the language_version parameter on decompile_assembly.

ILSpy produces clean output, but two optional flags can tighten it further:

  • remove_dead_code strips unreachable code paths that the compiler left in the IL. This is common with debug builds.
  • remove_dead_stores removes variable assignments whose values are never read.

Both flags are safe for source recovery — they remove only provably unreachable code.

If you only need one class, skip the project generation and decompile just that type:

"Decompile the MyApp.Data.CustomerRepository class from LegacyApp.dll"

This returns the C# source for that single type, which you can paste directly into a new project.