February 13th, 2020

Decompilation of C# code made easy with Visual Studio

Mark Downie
Principal Program Manager

Have you ever found yourself debugging a .NET project or memory dump only to be confronted with a No Symbols Loaded page? Or maybe experienced an exception occurring in a 3rd party .NET assembly but had no source code to figure out why? You can now use Visual Studio to decompile managed code even if you don’t have the symbols, allowing you to look at code, inspect variables and set breakpoints.

We have recently released a new decompilation and symbol creation experience in the latest preview of Visual Studio 2019 version 16.5 that will aid debugging in situations where you might be missing symbol files or source code. As we launch this feature, we want to ensure that we are creating the most intuitive workflows so please provide feedback.

Decompilation and PDB generation with ILSpy

Decompilation is the process used to produce source code from compiled code. In order to accomplish this we are partnering with ILSpy, a popular open source project, which provides first class, cross platform symbol generation and decompliation. Our engineering team is working to integrate ILSpy technology into valuable debugging scenarios.

What are symbol files? Why do you need them?

Symbol files represent a record of how the compiler translates your source code into Common Intermediate Language (CIL), the CIL is compiled by the Common Language Runtime and executed by the processor. The .NET compiler symbol files are represented by program database files (.pdb), and these files are created as part of the build. The symbol file maps statements in the source code to the CIL instructions in the executable.

Debuggers are able to use the information in the symbol file to determine the source file and line number that should be displayed, and the location in the executable to stop at when you set a breakpoint. Debugging without a symbol file would make it difficult to set breakpoints on a specific line of code or even step through code.

Visual Studio currently provides the option to debug code outside your project source code, such as .NET or third-party code your project calls by specifying the location of the .pdb (and optionally, the source files of the external code). However, in many cases finding the correct symbol files or source code may not be feasible.

By integrating decompilation directly into your debugging experiences we hope to provide developers with the most direct route to troubleshooting issues in 3rd party managed code. We are initially integrating the decompilation experiences into the Module Window, No Symbols Loaded, and Source Not Found page.

No Symbols Loaded/Source Not Found

There are a several ways in which Visual Studio will try to step into code for which it does not have symbols or source files available:

  • Break into code from a breakpoint or exception.
  • Step into code.
  • Switch to a different thread.
  • Change the stack frame by double-clicking a frame in the Call Stack window.

Under these circumstances, the debugger displays the No Symbols Loaded or Source Not Found page and provides an opportunity to load the necessary symbols or source.

In the following example I have opened a crash dump in Visual Studio and have hit an exception in framework code. I do not have the original source code so If I try to switch to the main thread, I see the No Symbols Loaded page. However, it is now possible to decompile the code directly on this page and see the origins of the exception.

Image vs decompilation no symbols loaded

Module Window

During debugging the Modules window is a great place to get information related to the assemblies and executables currently in memory. To open the Modules window, select Debug > Windows > Modules.

Once you have identified a module that requires decompilation, you can right-click on the module and select “Decompile Source to Symbol File”. This action creates a symbol file containing decompiled source which in turn permits you to step into 3rd party code directly from your source code.

It will also be possible to extract source code to disk by right clicking on a module with embedded source and clicking “Extract Embedded Source”. This process exports source files to a Miscellaneous files folder for further analysis. In the following example I open an extracted .cs file and set a break point to better understand the 3rd party code I am using.

Shows decompilation and source extraction from Visual Studio Module window

Some Considerations

Decompilation of the CIL format, used in .NET assemblies, back into a higher-level language like C# has some inherent limitations:

  • Decompiled source does not always resemble the original source code. Decompilation is best used to understand how the program is executing and not as a replacement for the original source code.
  • Debugging code that was decompiled from an assembly that was built using compiler optimizations may encounter the following issues:
    • Breakpoints not always binding to the matching sourcing location
    • Stepping may not always step to the correction
    • Async/await and yield state-machines may not be fully resolved
    • Local variables may not have accurate names
    • Some variables may not be able to be evaluated in the IL Stacks is not empty
  • Source code extracted from an assembly are placed in the solution as Miscellaneous file:
    • The name and location of the generated files is not configurable.
    • They are temporary and will be deleted by Visual Studio.
    • Files are placed in a single folder and any folder hierarchy that the original sources had is not used.
    • The file name for each file has a checksum hash of the file.
  • Decompilation of optimized or release modules produces non-user code. If the debugger breaks in your decompiled non-user code, for example, the No Source window will appear. In order to disable Just My Code navigate to Tools > Options (or Debug > Options) > Debugging > General, deselect Enable Just My Code.
  • Decompilation will only generate source code files in C#.

Try it now!

Download the preview and try out decompilation and let us how it works for you! Please reach out and give us feedback over at Developer Community. Finally, we also have a survey for collecting feedback on the new experiences here. We look forward to hearing from you.

Author

Mark Downie
Principal Program Manager

Mark Downie is a program manager on the Visual Studio Production Diagnostics team. He blogs about how you can use Visual Studio to get to the bottom of gnarly issues in production.

40 comments

Discussion is closed. Login to edit/delete existing comments.

  • Vladimir Velichkin

    My problem with this is that it is so painfully slow compared to plain ILSpy decompilation. It seems to take it half a minute to generate several files from a large assembly (think PresentationFramework – I know the sources are available anyway, it’s just a good example), compared to a few seconds for the entire assembly by using ILSpy directly.

    This is rather disappointing, but I am sure it will improve eventually.

  • PoisnFang

    For those scared of decompilation, you could just join the open source movement… but to the main point, decompilation has been around for a long time and this is just a tool to help developers. If someone wants to decompile your code and rebuild your project there are better applications out there.

  • Byron Adams

    Best feature I like is being able to debug into source that’s not even referenced by my solution.

  • Jan Pavliš

    I think that instead of placing all generated source code files in a single folder it could be useful to (optionally) place them in a directory tree by namespace of the class in the file - the same way IL Spy does it. Large assemblies contain thousands of classes and this would make finding what I'm looking for easier. Also I would welcome if there was an option to generate not only C# code, but...

    Read more
  • Hai Ha

    This is a great feature. I do debug of 3rd-party code a lot, most of the time to find out what they are doing wrong or see how they work to fix our code. To those who are worried their application being de-compiled: People do debug of 3rd-party library usually because the library itself involves in an issue. I myself care ZERO about your code because most codes are garbage, don't over-estimate it. Also if...

    Read more
  • Keith Patrick

    This could be a killer feature. I've lost count how many times I've installed the .Net Reflector VS addin to get just-in-time decompilation (and very nearly bought it last month). Every time, it's to debug a single issue where ILSpy code isn't quite matching up with what the debugger is telling me I've got....even if the add-in doesn't get the source exactly right, just being able to add watches makes all the difference in...

    Read more
  • Aaron Hudon

    How about built-in obfuscation?

    • Evgeny Vrublevsky

      I would say that obfuscation is an anti-feature, and shouldn’t be available by default.

  • Rene Gillmeister

    It’s really great how Microsoft cares about its customers’ intellectual property. Instead of making sure that at least basic protection is finally available, you are now making it even easier for crackers and other criminals to rob developers of their livelihood. And then to say: “You can protect your source code by your EULA. Simply forbid decompiling…”. I think this feature will cause great grief.

    • Patrick Smacchia

      This complain of “how do I protect my code from being decompiled then?!” and "Microsoft does not care about its customers’ intellectual property." is completely absurd. Since its inception in 2002 .NET compiled code can be decompiled and read crystal clear with popular tools like .NET Reflector, IL Spy, dotPeak… This is a direct consequence of having IL/byte code and a CLR with a JIT compiler.

      Since 2002 those that want to protect their compiled...

      Read more
      • Keith Patrick

        I'm of the belief that obfuscation is an ultimately pointless endeavor. There's some WinRT assemblies that don't like being opened up ILSpy/Reflector, but pretty much anything is still going to be able to be readable. If you want to protect your business logic, you can copyright it (or *maybe* patent it, but that's a gamble), or you can just host it on a web server, where your business logic stays on the secured...

        Read more
    • Mark DownieMicrosoft employee Author

      Thanks for the comment Rene. I hear your concern on protecting intellectual property and the desire for some form of protection. Your feedback is definitely welcome as we continue to evolve this feature. If you are willing, we could talk on a call, I would like to hear more about the kinds of protection you would anticipate .NET provide more generally.

      • A Jennig

        ILSpy is the best decompiler but was missing debugging capabilities like another decompiler.

        Did the team consider how integrating ILSpy and giving it debugging/breakpoint abilities makes it more convenient and easier to find any company's secret sauce? All that needs to be added is the ability to save an assembly after removing the license check (like another tool does) and Microsoft has created the perfect cracking tool - all integrating into Visual Studio - And many...

        Read more
      • Chuck Ryan

        My concern is the obvious script the Visual Studio development team is consistantly using to address the many areas where your customers do not like what you are doing. In the end it all boils down to “we are releasing this no matter what you think, we know best, but we will make some cosmetic changes to appease you”.

      • Rene Gillmeister

        In addition, if the CS files are to be saved for later review, they should be encrypted and only be readable with the decompiler.

      • Rene Gi

        My proposed solution: It should be an opt-in. Only digitally signed software with an Allow Decompilation option in the application manifest should be decompilable. Decompiling programs that do not comply should be considered illegal and their authors should be held liable for damages.

  • Vasiliy Grebinnyk

    Coool feature. If you care about intellectual property you must use pro obfuscator. I am personally strugling with a No Symbols Loaded page debugging my own code in nuget package. I hope to move all my sharing code into nuget packages if this feature really works.