As I was
blogging before, RedGate are assholes. They bought
Reflector, promised to keep it free, then asked money for it. But every crisis can be turned into an opportunity.
JetBrains promised a free decompiler tool and they have kept their word as they have released an early build. A total news to me, but not really a surprise, other software companies decided to build their own version in order to boost their visibility in the developer world. Telerik, for example, has just released JustDecompile, beta version.It is no secret that JetBrains is a company that I respect a lot, as they made ReSharper, the coolest tool I've ever had the pleasure to work with, but I will try to be as unbiased as possible in comparing the options. I have tried dotPeek on WPF's PresentationFramework.dll from the .NET framework 4.0, as I often need to check the sources in order to understand functionality or bugs.
As a footnote,
Reflector, just before it went commercial, could not decompile some of the code there. Not only it did not decompile it, but it presented empty methods like that was all there was in the code, with no warnings or errors or explicative comments. So, even if free, I bet Reflector would have sucked in the end, after getting into the money grabbing hands of RedGate.
dotPeek has seen and decompiled the code that Reflector did not. Also, I have to say that similar functionality like in ReSharper, finding usages, going to declaration, etc are making dotPeek a very nice tool to work with. What I did not quite like is that it doesn't have yet the functionality to save the sources to text files. But I am sure this is just a detail that was not implemented yet. Hopefully, they will provide a rich plugin model like old Reflector did.
Unfortunately, to download
JustDecompile, they need you to have a Telerik login in order to download, which, as everyone knows, simply sucks. No one likes a registration form, folks! Especially one that presents you with wonderful prechecked checkboxes for permission for Telerik to send you all kind of stupid promotions and newsletters. Also, the download is of a .msi file. Most developers like to see what they are installing and preferably just copy it from a file archive. Running the .msi took forever, including the mandatory 100% CPU utilization bit that I will never understand in installation products.
(coming from the .NET runtime optimization service, mscorsvw, called by ngen) But that's just the delivery system. Let's check out the actual thing.
JustDecompile starts reasonably fast and it also has a nice look, being build with Telerik controls and what not. The decompilation is a bit weird at first, since it shows only the method names and for a second there I thought it was as bad as Reflector was, but then I noticed the
Expand All Members button. The context menu is not nearly as useful as dotPeek's, but there are a lot of options in the top toolbar and the navigation via links is fast and intuitive. It also has no text saving options yet.
As the decompiled sources were, I noticed these differences:
- JustDecompiler places inline member declarations in constructors, dotPeek shows it inline. It might not seem an important thing, but an internal class gains a weird public constructor in order to place the declaration there, instead of using the only internal constructor that the class had. It looks strange too as its last line is base(); which is not even legal.
- dotPeek seems to want to cast everything in the source code. For example List list = (List) null;
- JustDecompiler shows a Dictionary TryGetValue method with a ref parameter, dotPeek shows the correct out.
- dotPeek creates really simple names for local scope variables like listand list1, JustDecompiler seems to create more meaningful names like attachedAnnotations
- JustDecompiler shows a class internal as dotPeek shows it as internal abstract.
- JustDecompiler seems to fail to decompile correctly indexer access.
- JustDecompiler doesn't seem to handle explicit interface implementations.
- JustDecompiler doesn't seem to decompile readonly fields.
- JustDecompiler transforms a piece of code into an if with a return in it and then some other code, dotPeek decompiles it into an if/else.
- JustDecompiler doesn't seem to handle Unicode characters. dotPeek correctly encodes them in source like "\x001B".
- dotPeek seems to join nested ifs in a single one, as opposed to JustDecompiler.
- JustDecompiler uses base. in order to access members coming from base classes, while dotPeek uses this.
I will stop here. I am sure there are many other differences.
My conclusion is that dotPeek could do with the naming algorithm JustDecompiler seems to use for local scope variables, but in most other ways is superior to JustDecompiler for now. As both programs are in beta, this could quickly change. I do hope that healthy competition between these two products (and, why not, shady developer meetings in bars over tons of beer and pizza, in order to compare ideas intercompanies) will result in great products. My only wish is that one of these products would become open source, but as both use proprietary bits from commercial products, I doubt it will happen.
Have fun, devs!
Update 23 Feb 2012:Spurred by a comment from Telerik, I again tried a (quick and dirty, mind you) comparison of the two .Net decompilation tools: JetBrains dotPeek and Telerik JustDecompile. Here are my impressions:
First of all, the Telerik tool has a really cute installer. I am certainly annoyed with the default Windows one and its weird error codes and inexplicable crashes. Now, that doesn't mean the Telerik installer does better in the error section, since I had none, but how could it not? The problem with the installation of JustDecompile is that it also tried to install (option checkboxes set by default) JustCode and JustTrace. The checkboxes themselves were something really custom, graphically, so I almost let them checked, since they looked as part of the background picture. If it weren't for my brain spam detector which went all red lights and alarm bells when seeing a really beautiful installer for a free tool, I might have installed the two applications.
Now for the decompilation itself. I was trying to see what the VisualBasic Strings.FormatNumber method contained. The results:
- dotPeek showed xml documentation comments, JustDecompile did not
- dotPeek showed default values for method parameters, JustDecompile did not
- JustDecompile could decompile the source in C#, VB and IL, dotPeek did only C#
- JustDecompile showed the source closer to the original source (I can say this because it also shows VB, which is probably the language in which Microsoft.VisualBasic was written), dotPeek shows an equivalent source, but heavily optimized, with things like ternary operators, inversions of if blocks and even removals of else sections if the if block can directly return from the method
- There are some decorative attributes that dotPeek shows, while JustDecompile does not (like MethodImplAttribute)
- dotPeek has a tabbed interface that allows the opening of more than a single file, JustDecompile has only a code view window
- dotPeek shows the code of a class in a window, in order to see a method, it scrolls to where the method is; JustDecompile shows a class as a stub, one needs to click on a method to see the implementation of only that method in the code window
My conclusion remains that dotPeek is a lot more usable than JustDecompile. As a Resharper user, I can accept that I am biased, but one of the major functionalities of a .Net decompiler is to show you usable code. While I can take individual methods or properties with JustDecompile and paste them in my code, I can take entire classes with dotPeek, which makes me choose dotPeek for the moment, no matter all the other points above. Of course, if any of the two tools would give me a button that would allow me to take a dll and see it as a Visual Studio project, it would quickly rise to the top of my choices.
Update 26 Apr 2013:I've again compared the two .Net decompilers. JustDecompile 1.404.2 versus dotPeek EAP 1.1.1.511. You might ask why I am comparing with the Early Access Program version. It is because JustDecompile now has the option to export the assembly to a Visual Studio project (yay!), but dotPeek only has this in the EAP version so far.
I have this to report:
Telerik's JustDecompile:
- the installer is just as cute as before, only it is for a suite called DevCraft, of which one of the products is JustDecompile
- something that seemed a bit careless is the "trial" keyword appearing in both download page and installer. If installing just JD, it is not trial
- again the checkboxes for JustCode and JustTrace are checked by default, but at least they are more visible in the list of products in the suite
- a Help Improve the Telerik Installer Privacy Policy checkbox checked by default appeared and it is not that visible
- the same need to have an account to Telerik in order to download JD
- when installing JD, it also installs the Telerik Control Panel a single place to download and manage Telerik products, which is not obvious from the installer
- the install takes about two minutes on my computer to a total size of 31MB, including the control panel
- if a class is in a multipart namespace like Net.Dns, it uses folders named Net.Dns if there is no class in the Net namespace
- not everything goes smoothly, sometimes the decompiler throws exceptions that are then logged in the code as comments, with the request to mail to JustDecompilePublicFeedback@telerik.com
- it creates the AssemblyInfo.cs file in a Properties folder, just like when creating a project
- resolves string concatenation with string.Concat, rather than using the '+' operator as in the original code
- resolves foreach loops into while(true) loops with breaks when a condition is met
- uses private static methods in a class with the qualified class name
- resolves inline variables, leaving the code readable
- overall it has a nicer decompiled code structure than dotPeek
- adds explicit default constructors to classes
- places generic class constraint at the end of constraints list, generating an exception
- it doesn't catch all reference assemblies, sometimes you have to manually add them to the list
- decompiles enum values to integer in method optional parameters default values, generating compilation errors
- decompiles default(T) to null in method optional parameters default values, generating compilation errors
- decompiles class destructors to Finalize methods which are not valid, generating compilation errors
- types of parameters in calls to base constructors are sometimes wrong
- places calls to base/this constructors at the end of constructor code blocks, which of course does not work, when you place more complex code in the calls
- doesn't understand cast to ValueType (which is somewhat obscure, I agree)
- really fucks up expressions trees like FluentNHibernate mapping classes, but I hate NHibernate anyway
- resolves if blocks with return in them to goto/label sometimes
- resolves readonly fields instantiated from a constructor to a mess that uses a local variable to set the field (which is not valid)
- doesn't resolve corectly a class name if it conflicts with the name of a local method or field
- inlines constants (although I don't think they can solve this)
- switch/case statements on Enum values sometimes gain weird extra case blocks
- sometimes it uses safe casting with value types (x as bool)
JetBrain's dotPeek:
- the EAP version has a standalone executable version which doesn't need installation
- the whole install is really fast and installs around 46MB
- as I said above, it does not have the Export to Project option until version 1.1
- the decompilation process is slower than JustDecompile's
- if a class is in a multipart namespace like Net.Dns, it uses a folder structure like Net/Dns
- sometimes things don't go well and it marks this with // ISSUE: comments, describing the problem. Note: these are not code exceptions, but issues with the decompiled code
- it inlines a lot of local variables, making the code more compact and less readable
- weird casting of items in string concatenations
- a tendency to strong typed casting, making the code less readable and generating compilation errors at times
- the AssemblyInfo.cs file is not created in a Properties folder
- when there are more classes in a single file, it creates a file for each, named as the original file, but prefixed with a number, instead of using the name of the class
- it has an option to create the solution for the project as well
- it creates types for anonymous types, and creates files with weird names for them, which are not really valid, screwing the project.
- it has problems with base constructor calls and constructor inheritance
- it has problems with out parameters, it makes a complete mess of them
- tries to create a type for Linq IQueryable results, badly
- it has problems with class names that are the same as names of namespaces (this is an issue of ReSharper as well, when it doesn't present the option to choose between a class name and a namespace name)
- resolves while(method) to invalid for loops
- it doesn't resolve corectly a class name if it conflicts with the name of a local method or field
- problems with explicit interface implementations: ISomething a=new Something(); a.Method(); (it declares a as Something, not ISomething)
- problems with decompiling linq method chains
- I found a situation where it resolved Decimal.op_Increment(d) for 1+d
- indirectly used assemblies are not added to the reference list
- it sometimes creates weird local variables like local_0, which are not declared, so not valid
- adds a weird [assembly: Extension] in the AssemblyInfo file, which is not valid
- a lot of messed up bool values resolved as (object) (bool) (value ? 1 : 0), which doesn't even work
- inlines constants (although I don't think they can solve this)
- __Null local1 = null; - really?
After decompiling, solving the issues and compiling again an assembly in the project I am working on I got these sizes:
JustDecompile: 409088
dotPeek: 395776
The original: 396288
Of course,
this is not really a scientific comparison between the two. I was excited by the implementation of Export to Project in both products and I focused mainly on that. The navigation between types and methods is vastly improved in JustDecompile and, to my chagrin, I have to admit that it may be easier and safer to use than dotPeek at this time. Good job, Telerik! Oh, and no, they have NOT paid me to do this research :-)