## File: README.md

# ILSpy [](https://nuget.org/packages/ICSharpCode.Decompiler)  [](https://hachyderm.io/@ilspy) [](https://bsky.app/profile/ilspy.bsky.social) [](https://visualstudiogallery.msdn.microsoft.com/8ef1d688-f80c-4380-8004-2ec7f814e7de) 

ILSpy is the open-source, cross-platform .NET assembly browser and decompiler. The desktop UI runs on Windows, Linux, and macOS (built on [Avalonia](https://avaloniaui.net/)).

Download: [latest release](https://github.com/icsharpcode/ILSpy/releases) | [latest CI build (master)](https://github.com/icsharpcode/ILSpy/actions?query=workflow%3A%22Build+ILSpy%22+branch%3Amaster+is%3Asuccess+event%3Apush) | [Microsoft Store (RTM versions only)](https://apps.microsoft.com/store/detail/ilspy-fresh/XP8C26VDWLP4T4)

Decompiler Frontends
-------

Aside from the cross-platform desktop UI ILSpy (downloadable via Releases, see also [plugins](https://github.com/icsharpcode/ILSpy/wiki/Plugins)), the following other frontends are available:

* Visual Studio 2022/2026 ship with decompilation support for F12 enabled by default (using our engines v8.2 and v9.1 respectively).
* Our Visual Studio 2022 extension [marketplace](https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.ILSpy2022) (works with VS 2026 as well)
* Our Visual Studio Code Extension [repository](https://github.com/icsharpcode/ilspy-vscode) | [marketplace](https://marketplace.visualstudio.com/items?itemName=icsharpcode.ilspy-vscode) | [open-vsx](https://open-vsx.org/extension/icsharpcode/ilspy-vscode)
* Our dotnet tool for Linux/Mac/Windows - check out [ILSpyCmd](ICSharpCode.ILSpyCmd) in this repository | [dotnet tool install](https://www.nuget.org/packages/ilspycmd/)
* [C# for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) ships with decompilation support as well. To enable, activate the setting "Enable Decompilation Support".
* In Visual Studio 2019, you have to manually enable F12 support. Go to Tools / Options / Text Editor / C# / Advanced and check "Enable navigation to decompiled source"
* Our [ICSharpCode.Decompiler](https://www.nuget.org/packages/ICSharpCode.Decompiler/) and [ILSpyX](https://www.nuget.org/packages/ICSharpCode.ILSpyX/) NuGet packages for your own projects
* Our Linux/Mac/Windows [PowerShell cmdlets](ICSharpCode.Decompiler.PowerShell) in this repository

Features
-------

 * Decompilation to C# (check out the [language support status](https://github.com/icsharpcode/ILSpy/issues/829))
 * Whole-project decompilation
 * Open from NuGet feed, open from running process in addition to disk and GAC (Windows-only)
 * Search for types/methods/properties (learn about the [options](https://github.com/icsharpcode/ILSpy/wiki/Search-Options))
 * Hyperlink-based type/method/property navigation, bookmarks
 * Base/Derived types navigation, history
 * Assembly metadata explorer ([feature walkthrough](https://github.com/icsharpcode/ILSpy/wiki/Metadata-Explorer))
 * BAML to XAML decompiler, !AvaloniaResources support
 * ReadyToRun binary support for .NET Core (see the [tutorial](https://github.com/icsharpcode/ILSpy/wiki/ILSpy.ReadyToRun))
 * Extensible via [plugins](https://github.com/icsharpcode/ILSpy/wiki/Plugins)
 * Additional features in DEBUG builds ([for the devs](https://github.com/icsharpcode/ILSpy/wiki/Additional-Features-in-DEBUG-Builds))

License
-------

ILSpy is distributed under the MIT License. Please see the [About](doc/ILSpyAboutPage.txt) doc for details, 
as well as [third party notices](doc/third-party-notices.txt) for included open-source libraries.

How to build
------------

#### Windows:

- Make sure Windows PowerShell (at least version) 5.0 or [PowerShell](https://github.com/PowerShell/PowerShell) 7+ is installed.
- Clone the ILSpy repository using git.
- Execute `git submodule update --init --recursive` to download the ILSpy-Tests submodule (used by some test cases).
- Install Visual Studio (documented version: 18.0/2026). You need the following workload components:
  - Workload ".NET Desktop Development". This workload includes the .NET Framework 4.8 SDK and the .NET Framework 4.7.2 targeting pack, as well as the [.NET 10.0 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) (ILSpy.csproj targets .NET 10.0, but we have net472 projects too). Our unit tests require [.NET 11.0 SDK](https://dotnet.microsoft.com/download/dotnet/11.0).
  - Workload "Visual Studio extension development" (Note: ILSpy.VSExtensions.slnx is separate from ILSpy.sln and thus this workload is optional)
  - Individual Component "MSVC v143 - VS 2022 C++ x64/x86 build tools" (or similar)
    - _The VC++ toolset is optional_; if present it is used for `editbin.exe` to modify the stack size used by ILSpy.exe from 1MB to 16MB, because the decompiler makes heavy use of recursion, where small stack sizes lead to problems in very complex methods.
- Open ILSpy.sln in Visual Studio.
  - NuGet package restore will automatically download further dependencies
  - Run project "ILSpy" for the ILSpy UI
  - Use the Visual Studio "Test Explorer" to see/run the tests
  - If you are only interested in a specific subset of ILSpy, you can also use
    - ILSpy.Desktop.slnf: for the cross-platform Avalonia UI and its tests
    - ILSpy.XPlat.slnf: for the cross-platform CLI (ilspycmd) or PowerShell cmdlets
    - ILSpy.VSExtensions.slnx: for the Visual Studio extensions

**Note:** Visual Studio includes a version of the .NET SDK that is managed by the Visual Studio installer - once you update, it may get upgraded too.
Please note that ILSpy is only compatible with the .NET 11.0 SDK and Visual Studio will refuse to load some projects in the solution (and unit tests will fail). 
If this problem occurs, please manually install the .NET 11.0 SDK from [here](https://dotnet.microsoft.com/download/dotnet/11.0).

#### Unix / Mac:

- Make sure [.NET 10.0 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) (for run) and [.NET 11.0 SDK](https://dotnet.microsoft.com/download/dotnet/11.0) (for tests) is installed.
- Make sure [PowerShell](https://github.com/PowerShell/PowerShell) is installed (formerly known as PowerShell Core)
- Clone the repository using git.
- Execute `git submodule update --init --recursive` to download the ILSpy-Tests submodule (used by some test cases).
- Use `dotnet build ILSpy.Desktop.slnf` to build the cross-platform Avalonia desktop UI; run it with `dotnet run --project ILSpy`.
- Use `dotnet build ILSpy.XPlat.slnf` to build only the CLI tool (ilspycmd) and PowerShell cmdlets.

How to contribute
-----------------

- Report bugs
- If you want to contribute a pull request, please add https://github.com/icsharpcode/ILSpy/blob/master/BuildTools/pre-commit to your `.git/hooks` to prevent checking in code with wrong formatting. We use tabs and not spaces. The build server runs the same script, so any pull requests using wrong formatting will fail.

Current and past [contributors](https://github.com/icsharpcode/ILSpy/graphs/contributors).

Privacy Policy for ILSpy
------------------------

ILSpy does not collect any personally identifiable information, nor does it send user files to 3rd party services. 
ILSpy does not use any APM (Application Performance Management) service to collect telemetry or metrics.

---

## File: doc/ILAst Pattern Matching.md

ILAst Pattern Matching
=================

Some IL instructions are classified as "patterns".
```c#
abstract class PatternMatchILInstruction : IStoreInstruction {
   public ILInstruction TestedOperand { get; }
   public ILVariable Variable { get; } // variable that receives the match result; may also be a temporary
}

public bool IsPattern(this ILInstruction inst, out ILInstruction testedOperand) => inst switch {
    PatternMatchILInstruction pm => testedOperand = pm.TestedOperand; return true;
    LogicNot logicNot => IsPattern(logicNot.Operand, out testedOperand),
    Comp comp => testedOperand = comp.Left; return IsConstant(comp.Right);
}
```
Every `match.*` instruction has the following properties:
  * The `TestedOperand` specifies what gets matched against the pattern.
  * The `Variable` stores the value of `TestedOperand` (after converting to the matched type, if appropriate).
    * If this variable is also used outside the `match.*` node, it corresponds to the C# `single_variable_designation`.
    * Otherwise it's a temporary used for pattern matching.
    * I think in both cases it should have VariableKind.PatternVar
  * The match instruction evaluates to `StackType.I4`: 0 if the pattern was matched, 1 otherwise.

Some `match` instructions have a body with `List nestedPatterns`. Here every nested pattern must be a pattern according to `IsPattern()`, and the `testedOperand` of each must be a member of the `Variable` of the parent pattern. (members are: field, property, or deconstruction.result).
(exception: `match.and`/`match.or`, these instead require the `testedOperand` to be exactly the `Variable` of the parent pattern)


Examples
--------
1) `expr is var x`
    =>
    `match.var(x = expr)`
    =>
    ```
    Block (VarPattern) {
	    stloc x(expr)		// single eval expr
	    final: ldc.i4 1		// match always
    }
    ```
2) `expr is T x`
	=>
    `match.type T(x = expr) {}`
    =>
	```
    Block (TypePattern) {
        stloc x(isinst T(expr))
        final: x != null
    }
	```
3) `expr is C { A: var x } z`
	=>
    ```
    match.type C(z = expr) {
       match.var(x = z.A)
    }
    ```
    =>
	```
    Block (TypePattern) {
        stloc z(isinst T(expr))
        final: (z != null)
            && Block(VarPattern) {
                 stloc x(z.A)
                 final: ldc.i4 1
               }
    }
	```
4) `expr is C { A: var x, B: 42, C: { A: 4 } } z`
    =>
    ```
    match.type C(z = expr) {
        match.var (x = z.A),
        comp (z.B == 42),
        match.recursive (temp2 = z.C) {
            comp (temp2.A == 4)
        }
    }
    ```
	=>
	```
    Block (TypePattern) {
        stloc z(isinst C(expr))
        final: (z != null)
            && Block(VarPattern) {
                 stloc x(z.A)
                 final: ldc.i4 1
               }
            && comp (z.B == 42)
            && Block(RecursivePattern) {
                 stloc temp2(z.C)
                 final: (temp2 != null)
                     && comp (temp2.A == 4)
               }
    }
	```
5) `expr is C(var x, var y, <4) { ... }`
   =>
   ```
   match.recursive.type.deconstruct(C tmp1 = expr) {
       match.var(x = deconstruct.result0(tmp1)),
       match.var(y = deconstruct.result1(tmp1)),
       comp(deconstruct.result2(tmp1) < 4),
   }
   ```

6) `expr is C(1, D(2, 3))`
    =>
    ```
    match.type.deconstruct(C c = expr) {
        comp(deconstruct.result0(c) == 1),
        match.type.deconstruct(D d = deconstruct.result1(c)) {
            comp(deconstruct.result0(d) == 2),
            comp(deconstruct.result1(d) == 2),
        }
    }
    ```
    
7) `x is >= 0 and var y and <= 100`
    ```
    match.and(tmp1 = x) {
        comp(tmp1 >= 0),
        match.var(y = tmp1),
        comp(tmp1 <= 100)
    }
    ```

8) `x is not C _`
    =>
    ```
    logic.not(
        match.type(C tmp1 = x) {}
    )
    ```

9) `expr is (var a, var b)` (when expr is object)
    =>
    ```
    match.type.deconstruct(ITuple tmp = expr) {
        match.var(a = deconstruct.result0(tmp)),
        match.var(b = deconstruct.result1(tmp)),
    }
    ```
    
10) `expr is (var a, var b)` (when expr is ValueTuple)
    =>
    ```
    match.recursive(tmp = expr) {
        match.var(a = tmp.Item1),
        match.var(b = tmp.Item2),
    }
    ```

---

## File: doc/README.md

# Files

## License-Related

|File|Contents/Usage|
|---|---|
|ILSpyAboutPage.txt|Binary inclusion in ILSpy for About listing ILSpy components' licenses and third party notices link|
|third-party-notices.txt|Binary inclusion in ILSpy for third party libraries and code used in ILSpy and its components|
|copyright.txt|Copyright notice for ILSpy|
|license.txt|MIT license for ILSpy|

## Other

|File|Contents|
|---|---|
|   |   |

---

## File: ICSharpCode.Decompiler.PowerShell/README.md

# ILSpy PowerShell Module

Built using https://github.com/PowerShell/PowerShell/blob/master/docs/cmdlet-example/command-line-simple-example.md as guideline

Sample usage: Demo.ps1

Tested with: PowerShell 5.1 on Windows, PowerShell 7+ on Windows and Mac



## Missing

Publishing to https://www.powershellgallery.com/

* https://learn.microsoft.com/en-us/powershell/gallery/how-to/publishing-packages/publishing-a-package
* https://learn.microsoft.com/en-us/powershell/gallery/concepts/publishing-guidelines

## Links for developing PS cmdlets

* https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/how-to-write-a-simple-cmdlet
* https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands
* https://github.com/mmaitre314/PowerShellGet-Test-Binary-Module
* https://www.red-gate.com/simple-talk/dotnet/net-development/using-c-to-create-powershell-cmdlets-beyond-the-basics/
* https://www.google.com/search?q=write+a+module+for+powershell+core

---

## File: ICSharpCode.ILSpyCmd/AsContainer/README.md

# ILSpyCmd in Docker

Inspired by https://trustedsec.com/blog/hunting-deserialization-vulnerabilities-with-claude (and thus https://github.com/berdav/ilspycmd-docker)

## Building the Image

There are two dockerfiles available - one for interactive use of ilspycmd (exploration), and the other for driving it from the outside (automation)

### Interactive 

`docker build -t ilspycmd:91interactive . -f Dockerfile`

`docker run --rm -it -v ./:/docker ilspycmd:91interactive`

### Automation

`docker build -t ilspycmd:91forautomation . -f DockerfileForAutomation`

`docker run --rm -v ./:/infolder -v ./out:/outfolder ilspycmd:91forautomation "/home/ilspy/.dotnet/tools/ilspycmd -p -o /outfolder /infolder/sample.dll"`

---

## File: ICSharpCode.ILSpyCmd/README.md

# ilspycmd .NET Tool 

To install:

``` bash
dotnet tool install --global ilspycmd
```

Help output (`ilspycmd --help`):

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Generate HTML diagrammers

Once you have an output folder in mind, you can adopt either of the following strategies
to generate a HTML diagrammer from a .Net assembly using the console app.

### Manually before use

**Create the output folder** in your location of choice and inside it **a new shell script**.

Using the CMD shell in a Windows environment for example, you'd create a `regenerate.cmd` looking somewhat like this:


..\..\path\to\ilspycmd.exe ..\path\to\your\assembly.dll --generate-diagrammer --outputdir .


With this script in place, run it to (re-)generate the HTML diagrammer at your leisure. Note that `--outputdir .` directs the output to the current directory.

### Automatically

If you want to deploy an up-to-date HTML diagrammer as part of your live documentation,
you'll want to automate its regeneration to keep it in sync with your code base.

For example, you might like to share the diagrammer on a web server or - in general - with users
who cannot or may not regenerate it; lacking either access to the ilspycmd console app or permission to use it.

In such cases, you can dangle the regeneration off the end of either your build or deployment pipeline.
Note that the macros used here apply to [MSBuild](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild) for [Visual Studio](https://learn.microsoft.com/en-us/visualstudio/ide/reference/pre-build-event-post-build-event-command-line-dialog-box) and your mileage may vary with VS for Mac or VS Code.

#### After building

To regenerate the HTML diagrammer from your output assembly after building,
add something like the following to your project file.
Note that the `Condition` here is optional and configures this step to only run after `Release` builds.

```xml
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
  <Exec Command="$(SolutionDir)..\path\to\ilspycmd.exe $(TargetPath) --generate-diagrammer --outputdir $(ProjectDir)diagrammer" />
</Target>
```

#### After publishing

If you'd rather regenerate the diagram after publishing instead of building, all you have to do is change the `AfterTargets` to `Publish`.
Note that the `Target` `Name` doesn't matter here and that the diagrammer is generated into a folder in the `PublishDir` instead of the `ProjectDir`.

```xml
<Target Name="GenerateHtmlDiagrammer" AfterTargets="Publish">
  <Exec Command="$(SolutionDir)..\path\to\ilspycmd.exe $(TargetPath) --generate-diagrammer --outputdir $(PublishDir)diagrammer" />
</Target>
```

### Usage tips

**Compiler-generated** types and their nested types are **excluded by default**.

Consider sussing out **big source assemblies** using [ILSpy](https://github.com/icsharpcode/ILSpy) first to get an idea about which subdomains to include in your diagrammers. Otherwise you may experience long build times and large file sizes for the diagrammer as well as a looong type selection opening it. At some point, mermaid may refuse to render all types in your selection because their definitions exceed the maximum input size. If that's where you find yourself, you may want to consider
- using `--generate-diagrammer-include` and `--generate-diagrammer-exclude` to **limit the scope of the individual diagrammer to a certain subdomain**
- generating **multiple diagrammers for different subdomains**.

### Advanced configuration examples

Above examples show how the most important options are used. Let's have a quick look at the remaining ones, which allow for customization in your project setup and diagrams.

#### Filter extracted types

Sometimes the source assembly contains way more types than are sensible to diagram. Types with metadata for validation or mapping for example. Or auto-generated types.
Especially if you want to tailor a diagrammer for a certain target audience and hide away most of the supporting type system to avoid noise and unnecessary questions.

In these scenarios you can supply Regular Expressions for types to `--generate-diagrammer-include` (white-list) and `--generate-diagrammer-exclude` (black-list).
A third option `--generate-diagrammer-report-excluded` will output a `.txt` containing the list of effectively excluded types next to the HTML diagrammer containing the effectively included types.


ilspycmd.exe **--generate-diagrammer-include Your\.Models\..+ --generate-diagrammer-exclude .+\+Metadata|.+\.Data\..+Map --generate-diagrammer-report-excluded** ..\path\to\your\assembly.dll --generate-diagrammer --outputdir .


This example
- includes all types in the top-level namespace `Your.Models`
- while excluding
  - nested types called `Metadata` and
  - types ending in `Map` in descendant `.Data.` namespaces.

#### Strip namespaces from XML comments

You can reduce the noise in the XML documentation comments on classes on your diagrams by supplying a space-separated list of namespaces to omit from the output like so:


ilspycmd.exe **--generate-diagrammer-strip-namespaces System.Collections.Generic System** ..\path\to\your\assembly.dll --generate-diagrammer --output-folder .


Note how `System` is replaced **after** other namespaces starting with `System.` to achieve complete removal.
Otherwise `System.Collections.Generic` wouldn't match the `Collections.Generic` left over after removing `System.`, resulting in partial removal only.

#### Adjust for custom XML documentation file names

If - for whatever reason - you have customized your XML documentation file output name, you can specify a custom path to pick it up from.


ilspycmd.exe **--generate-diagrammer-docs ..\path\to\your\docs.xml** ..\path\to\your\assembly.dll --generate-diagrammer --output-folder .

---

## File: ICSharpCode.ILSpyX/MermaidDiagrammer/ReadMe.md

# How does it work?

To **extract the type info from the source assembly**, ILSpy side-loads it including all its dependencies.

The extracted type info is **structured into a model optimized for the HTML diagrammer** and serialized to JSON. The model is a mix between drop-in type definitions in mermaid class diagram syntax and destructured metadata about relations, inheritance and documentation comments.

> The JSON type info is injected into the `template.html` alongside other resources like the `script.js` at corresponding `{{placeholders}}`. It comes baked into the HTML diagrammer to enable
> - accessing the data and
> - importing the mermaid module from a CDN
>
> locally without running a web server [while also avoiding CORS restrictions.](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#file_origins)

In the final step, the **HTML diagrammer app re-assembles the type info** based on the in-app type selection and rendering options **to generate [mermaid class diagrams](https://mermaid.js.org/syntax/classDiagram.html)** with the types, their relations and as much inheritance detail as you need.

---

## File: ILSpy.AddIn.VS2022/README.md

Test cases for various types of projects as well as corresponding test plans are located in a separate repository.

[https://github.com/icsharpcode/ILSpy-Addin-tests](https://github.com/icsharpcode/ILSpy-Addin-tests)

---

## File: ILSpy.Installer/README.md

# Building the Installer

## Dependencies

See https://github.com/oleg-shilo/wixsharp/wiki#dependencies

```
dotnet tool install --global wix
```

GitHub runners installed software https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md at time 
of writing WiX Toolset 3.14.1.8722


## ILSpy Binaries

It is mandatory to first publish(.ps1) the respective target platforms, then setup can be built, eg

```
msbuild ILSpy.Installer.sln /p:Configuration="Release" /p:Platform="Any CPU"
msbuild ILSpy.Installer.sln /p:Configuration="Release" /p:Platform="Any CPU" /p:DefineConstants="ARM64"
```