Click here to Skip to main content
15,879,239 members
Articles / Programming Languages / C#

See the Intermediate Language for C# Code

Rate me:
Please Sign up or sign in to vote.
4.94/5 (53 votes)
12 Sep 2019CPOL6 min read 85.7K   1.9K   75   49
Introducing 'Sil' - the addin that lets you right click on code and quickly inspect the Common Intermediate Language the compiler generates for it.

Introduction

Sil is an addin for Visual Studio that lets you quickly disassemble and inspect code. How does it work?

First, find some code that you're interested in:

Image 1

Next, right click on the method name (or property, or class, etc.) and choose 'Disassemble':

Image 2

Finally, the disassembly for your selection is shown in a new document window, with some extra functionality such as the ability to show or hide the source comments:

Image 3

Why would we care about the disassembly?

1. Problem Solving

C# has a lot of syntactic sugar - lambda expressions, linq, using statements, multicast delegates and so on. Sometimes, if you're investigating a bug or a problem, it can help to see what's actually going on at a lower level in your code.

2. Education

There are many things we learn about .NET and C# - and these are often quite high level. It's great that we don't have to care about what assembly is generated by the constructs we use. However, most of us developer types are nerds and tinkerers - we want to understand what's going on, how it works and broaden our knowledge. We all know that a using block will dispose of its target IDisposable object even if an exception is thrown - but how? If we catch an exception as type System.Exception and silently consume it, our code will continue to execute - right? But what if it's a ThreadAbortException? That automatically gets re-thrown - how? Seeing the assembly can teach you more about how C# and the .NET Framework actually work.

In this article, I'll show you how to use Sil, and also describe how it works - you can use the code as a starting point for your own Visual Studio addins. I will also be writing a short series of articles on Common Intermediate Language from the point of view of a .NET developer.

Let Me Try It!

If you're already sold on the prospect of madly inspecting each of your functions through the microscope and want to give Sil a try - just download the installer at the top of the article. Sil works as an addin for Visual Studio 2010 and 2012, there's also a standalone application that lets you disassemble any managed assembly.

Once you've installed Sil, just open any C# code and right click on something you're interested in. If it's a method name, the method will be disassembled. The same applies to properties, fields, events, delegates, enumerations and many other constructs. If Sil can't work out specifically what you're trying to disassemble, it'll disassemble the whole assembly for you.

The Standalone Application

You can run Sil as a standalone application. Open it up and choose 'File > Disassemble' or just drop an assembly onto the main window. One useful feature of the standalone app is that the entire assembly contents will be shown as a structured tree on the left hand side of the main window, which lets you look around in your assembly easily.

Image 4

How Sil Works

Sil is not really very smart. It is broken into a few basic components.

Sil API

This class library provides the core functionality, an object for disassembling assemblies (which creates a DisassembledAssembly instance). Alongside this, there are some other entities defined, such as DisassembledClass and DisassembledEnumeration.

Sil UI

This is a WPF User Control library that contains the main 'SilView' user control. This view is used to present a DisassembledAssembly. It also provides some basic functionality (such as turning on or off the comments).

Sil.SV2010

The Visual Studio 2010 addin. This adds the 'Disassemble' command to the code editor context menu and wires it up. It uses the Sil API for the logic of disassembling your selection, and the Sil UI to present it in a tool window.

Sil.SV2012

The Visual Studio 2012 addin. This adds the 'Disassemble' command to the code editor context menu and wires it up. It uses the Sil API for the logic of disassembling your selection, and the Sil UI to present it in a tool window.

Sil

The standalone application. This is a WPF app that uses the API to disassemble an assembly, and presents it via the Sil UI.

Sil also uses some other external components.

ildasm

The ildasm tool from Microsoft is used to actually disassemble the assembly.

AvalonEdit

The fantastic AvalonEdit library is used to create a syntax highlighted assembly text editor window.

Using the API

You can use the Visual Studio Addin, or the standalone application, but you can also use the API directly if you like, I'll highlight how the library is used with a few simple examples.

Example 1: Disassemble an Assembly

In this example, we use the Disassembler object from the SilAPI to create a DisassembledAssembly. We then write the raw IL to a file.

C#
//  Disassemble the assembly.
DisassembledAssembly disassembledAssembly = 
        Disassembler.DisassembleAssembly(@"SomeAssembly.dll");
 
//  Write out the assembly to a file.
using(var stream = new FileStream(@"SomeAssembly.il", FileMode.Create, FileAccess.Write))
using (var writer = new StreamWriter(stream))
{
    writer.Write(disassembledAssembly.RawIL);
}

Some points:

  • The Disassembler is an object you'll use a lot if you're working with Sil - it's the class that will actually perform the disassembling operation.
  • A DisassembledAssembly not only contains the raw IL, but also the classes, structures, events and so on.

Example 2: Discover Classes in an Assembly

A DisassembledAssembly object contains a graph of the contents of the assembly. This means you can enumerate through various elements of an assembly.

C#
//  Disassemble the assembly.
DisassembledAssembly disassembledAssembly = 
                     Disassembler.DisassembleAssembly(@"SomeAssembly.dll");
 
//  Go through each class.
foreach (var disassembledClass in disassembledAssembly.Classes)
{
    //  Write out some details on the class.
    Console.WriteLine("Found class: " + disassembledClass.ShortName);
    Console.WriteLine("Fields: " + disassembledClass.Fields.Count());
    Console.WriteLine("Methods: " + disassembledClass.Methods.Count());
}

Some useful properties like this on the assembly are:

  • Classes: The classes defined in the assembly
  • AllClasses: The classes defined in the assembly, including nested classes
  • Structures / AllStructures: Gets structures in the assembly, optionally including nested structures
  • Interfaces / AllInterfaces: Gets the interfaces
  • Delegates / AllDelegates: Gets the delegates
  • Enumerations / AllEnumerations: Gets the enumerations
  • AllFields: Gets all fields in all objects
  • AllProperties: Gets all properties in all objects
  • AllEvents: Gets all events in all objects
  • AllMethods: Gets all methods

Example 3: Searching for an Entity in an Assembly

In client applications like the Visual Studio Addin, we often know the long name of what we're looking for, and what it is (e.g., when the user right-clicks on a class, we know it's a class they've selected and what its full name is). The API exposes a method for searching an assembly.

C#
public static void SearchAssembly()
{
    //  Disassemble the assembly.
    DisassembledAssembly disassembledAssembly = 
                         Disassembler.DisassembleAssembly(@"SomeAssembly.dll");
 
    //  Create a disassembly target that targets the interface named 'ISomeInterface'.
    DisassemblyTarget target = new DisassemblyTarget
              (DisassemblyTargetType.Interface, @"SimeAssembly.ISomeInterface");
 
    //  Search for the interface.
    DisassembledEntity entity = disassembledAssembly.FindDisassembledEntity(target);
 
    //  If we found it, show the IL.
    if(entity != null)
        Console.WriteLine(entity.RawIL);
} 

Where Next?

From here, my plan is to write a short series of articles on Common Intermediate Language, as a reference for those who might want to learn a bit more about it. I've got some plans for Sil as well. Currently on the roadmap, I'm looking at:

  1. An automatic 'annotate' feature - if you select a line of assembly, there's a human readable description of what it means at the bottom of the screen.
  2. The ability to disassemble a selection of code, for example, a few lines of a method.
  3. Support for the Assembly Tree in the Addin, not just the standalone application.

If you have a particular desire for a feature or would like to get involved, get in touch! You can find the code on GitHub at github.com/dwmkerr/sil.

Known Issues

There are a few issues to be aware of when working with Sil.

  1. Visual Basic is not supported. It might work - I haven't tried. Support for VB is not on the roadmap, but if I get enough requests for it, then I'll certainly add it.
  2. I've seen some oddities with disassembling template classes - sometimes, the correct class cannot be found. This will be resolved very soon, you can follow the progress on GitHub.
  3. The project you're working on has to be built and up to date for Sil to be able to disassemble it. If you make changes to your code, then build it before you run Sil.

History

  • 7th June, 2013: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United Kingdom United Kingdom
Follow my blog at www.dwmkerr.com and find out about my charity at www.childrenshomesnepal.org.

Comments and Discussions

 
QuestionIt's a nice idea, but it doesn't appear to work for me Pin
OriginalGriff8-Jun-13 4:25
mveOriginalGriff8-Jun-13 4:25 
AnswerRe: It's a nice idea, but it doesn't appear to work for me Pin
Dave Kerr8-Jun-13 7:15
mentorDave Kerr8-Jun-13 7:15 
GeneralRe: It's a nice idea, but it doesn't appear to work for me Pin
OriginalGriff8-Jun-13 7:54
mveOriginalGriff8-Jun-13 7:54 
GeneralRe: It's a nice idea, but it doesn't appear to work for me Pin
Dave Kerr9-Jun-13 2:15
mentorDave Kerr9-Jun-13 2:15 
GeneralRe: It's a nice idea, but it doesn't appear to work for me Pin
OriginalGriff9-Jun-13 2:50
mveOriginalGriff9-Jun-13 2:50 
GeneralRe: It's a nice idea, but it doesn't appear to work for me Pin
Dave Kerr16-Jun-13 3:47
mentorDave Kerr16-Jun-13 3:47 
GeneralRe: It's a nice idea, but it doesn't appear to work for me Pin
OriginalGriff16-Jun-13 3:58
mveOriginalGriff16-Jun-13 3:58 
GeneralRe: It's a nice idea, but it doesn't appear to work for me Pin
OriginalGriff16-Jun-13 4:09
mveOriginalGriff16-Jun-13 4:09 
GeneralRe: It's a nice idea, but it doesn't appear to work for me Pin
Dave Kerr16-Jun-13 4:42
mentorDave Kerr16-Jun-13 4:42 
GeneralNice - I like it, A vote of 5 Pin
cvogt614577-Jun-13 5:22
cvogt614577-Jun-13 5:22 
GeneralRe: Nice - I like it, A vote of 5 Pin
Dave Kerr7-Jun-13 6:02
mentorDave Kerr7-Jun-13 6:02 
BugFound a bug Pin
BotCar5-Jun-13 20:52
BotCar5-Jun-13 20:52 
GeneralRe: Found a bug Pin
Dave Kerr5-Jun-13 21:08
mentorDave Kerr5-Jun-13 21:08 
SuggestionRe: Found a bug Pin
BotCar6-Jun-13 5:27
BotCar6-Jun-13 5:27 
GeneralRe: Found a bug Pin
Dave Kerr6-Jun-13 11:13
mentorDave Kerr6-Jun-13 11:13 
GeneralRe: Found a bug Pin
Dave Kerr6-Jun-13 12:40
mentorDave Kerr6-Jun-13 12:40 
GeneralRe: Found a bug Pin
BotCar6-Jun-13 20:03
BotCar6-Jun-13 20:03 
GeneralRe: Found a bug Pin
DanielSheets7-Jun-13 1:51
DanielSheets7-Jun-13 1:51 
GeneralRe: Found a bug Pin
Dave Kerr7-Jun-13 2:51
mentorDave Kerr7-Jun-13 2:51 
GeneralRe: Found a bug Pin
DanielSheets7-Jun-13 4:16
DanielSheets7-Jun-13 4:16 
GeneralMy vote of 5 Pin
LoveJenny5-Jun-13 15:08
LoveJenny5-Jun-13 15:08 
GeneralRe: My vote of 5 Pin
Dave Kerr5-Jun-13 21:08
mentorDave Kerr5-Jun-13 21:08 
GeneralMy vote of 5 Pin
Florian Rappl5-Jun-13 12:42
professionalFlorian Rappl5-Jun-13 12:42 
GeneralRe: My vote of 5 Pin
Dave Kerr5-Jun-13 21:07
mentorDave Kerr5-Jun-13 21:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.