Tuesday, May 27, 2014

Decompiling BAML

We know that XAML is a declarative markup language. XAML simplifies creating a UI for .NET application created using WPF or Silverlight. It is simple and easy to create UI elements using XAML, and then separate the design from run-time logic by using code-behind files, joined to the markup by partial class definitions. So what is a BAML ?

BAML is the short form of Binary Application Markup Language, as the name implies it is a binary representation of the XAML file containing implementation details. It is nothing but  parsed, tokenism and XAML that is converted into binary format. Tokenized  means lengthier bits of XAML are replaced with shorter tokens. It is compressed declarative format that is faster to load and parse also it is smaller in size as compared to regular XAML.

So when you compile a WPF project, all XAML files whose build action are set to Page or Resource gets converted to BAML and then embedded as resource in the assembly. So now you have a binary object that is smaller and also optimized in a way that makes it faster to parse at runtime. BAML gets embedded as a resource so developer don't need to worry about linking,parsing or referencing anything  except calling InitializeComponent() in code-behind.

BAML is converted to implementation code during runtime, internally it is used for creating objects. If  you set the x:shared attribute to false, a new copy is created from the BAML every time you use the object. In earlier versions developers didn't have access to BAML, After WPF 4 the new implementation of XamlReader.Load(), BAML loading, Control & DataTemplates functionality with a new engine built on top of the new System.Xaml.dll, I know back in the early days of WPF that CAML was generated rather than BAML, looks like the WPF team has decided to eliminate it, and keep the BAML version.

Baml2006Reader :
Again as most of us know that in WPF, UI can be created either by code or by XAML-which is basically an declarative XML to describe object graphs. This approach makes UI development  easy and fast but parsing XAML file at runtime is quite expensive. So the MarkupCompiler converts the XAML file to BAML.The BAML API is something unique of WPF and was not public until .NET 4.0. Now it's available through the Baml2006Reader implementation. The following code shows how to load a BAML stream .Baml2006Reader uses Reflection to load the assemblies needed for decompilation, which is a little expensive.
var reader = new Baml2006Reader(stream);
var writer = new XamlObjectWriter(reader.SchemaContext);
while(reader.Read())
{
    writer.WriteNode(reader);
}
return writer.Result;
A simple way to decompile the generated BAML is by using the dotPeek from JetBrains or .NET Reflector. Lets walk through the process of installing the plugin.

dotPeek : We have to build and install a plugin for dotPeek. To install the plugin follow this steps.
  1. Download the addin Baml4dotPeek  from the github project https://github.com/cprieto/Baml4dotPeek
  2. Build the project, you might have to update reference to point to your dotPeek bin folder.
  3. A successful  build will generate a output file "BamlFromResource.dll".
  4. Copy this file to the dotpeek bin directory.
  5. Restart dotPeek, and verify form the Tools|Options, if you have the BamlDecompiler.



Once you have the plugin installed open any WFP project and expand the directory tree to find the resources . From the resources you will find some baml file, select any file and the window on the right will display the xaml for that resource.




Note: For Silverlight the XAML files are not converted in to BAML.When you build a Silverlight project a .xap file is created, it is just a .zip-file containing an AppManifest.XAML and all resources in your project compiled as dll's.  You can verify that by opening a dll in dotPeek or Reflector, it will show the XAML-files and other resources.