Hopefully you’ve had a chance to check out the many add-ins available to extend .NET Reflector’s core decompilation functionality, as well as the suite of tools that use Reflector to extend their own capabilities. Silverlight Spy is one such tool with such an extensive set of functionality that it’s likely there things about it that you’ve missed.
If you’ve not used it yet, Silverlight Spy is a runtime inspector tool providing unprecedented access to all aspects of any Silverlight and Windows Phone application. It allows you to explore the UI element tree, monitor events, extract XAML, interactively execute DLR code, view statistics and much, much more.
We invited Koen Zwikstra, the creator of Silverlight Spy (& a former Silverlight MVP), to tell us about some of the hidden gems in his flagship tool, and how the tool integrates with .NET Reflector. In this exclusive guest post, he explains a number of features that you may not have discovered yet.
First of all, as the name suggests, Silverlight Spy is capable of “spying” on Silverlight applications. The latest release supports applications that are built for Silverlight versions 2, 3, 4 and 5, and supports Silverlight applications which are targetting in-browser as well as out-of-browser scenarios.
A little-known fact is that Silverlight Spy also happily supports Windows Phone applications; almost all inspector features available to Silverlight applications are available to Windows Phone apps as well. All you need to do for Silverlight Spy to support Windows Phone apps is to run the application in the emulator that comes with the Windows Phone SDK (both version 7.0 and 7.1 are fine).
Local database support
Silverlight Spy supports inspection of SQL Server Compact Edition database files found in the XAP package and isolated storage. These database files are used by Windows Phone Mango applications for local database support. Whenever Silverlight Spy detects a local database file in the XAP package or isolated storage, it automatically allows the user to expand the file in the Explorer and inspect tables, columns, indexes and table data. A local database file is identified by the .sdf file extension, and databases that are password protected are also supported.
There are all sorts of gems in the DLR shell, and I’m going to briefly introduce you to some of the shiniest ones. The Dynamic Language Runtime shell allows for interactively executing dynamic language code in the Silverlight application domain, and advanced querying and automation of Silverlight applications. The shell also provides full access to any runtime object in the Silverlight AppDomain.
The DLR Shell presents a user interface that is similar to SQL Server Query Analyzer; you just need to type your DLR code in the DLR shell and hit Execute to execute the code, and then view the results in the output pane. Silverlight Spy ensures that the required DLR assemblies are loaded into the Silverlight AppDomain, and there is no need to reference the DLR assemblies in the Silverlight application. The DLR Shell also supports the Python and Ruby DLR languages.
Silverlight Spy even exposes an API for automating Silverlight applications and Silverlight Spy itself inside the DLR Shell. The API is available in the FirstFloor.SilverlightSpy.Interop assembly that is automatically loaded for any application that is viewed by Silverlight Spy. The following Python snippet is an example of how to use the API to retrieve information from an application and Silverlight Spy. This particular snippet outputs details about the application root visual and the current selected element in the user interface.
from FirstFloor.SilverlightSpy.Interop import *
print ‘Root visual: ‘ + str(Spy.Current.RootVisual.Element)
print ‘Selected visual: ‘ + str(Spy.Current.SelectedVisual.Element)
The DLR Shell output supports both plain text output messages and output tables, and the output is entirely defined by the DLR script that is executed, and you can use DLR output functions such as print to write data to the output. The DLR engine created by Silverlight Spy redirects the output stream directly to the output window of the DLR Shell.
The output can include up to eight output tables, where each table appears in its own tab in the output pane. An output table is visualized by a sortable grid, and as such provides a convenient method for displaying DLR output. DLR output tables are created by programmatically adding them to the output, which is represented by a global variable named out, and always available to all scripts in the DLR shell. The out is a variable of type DlrOutput, and exposes methods for managing DLR output tables.
The following Python code snippet demonstrates the use of adding a table with rows to the output.
table = out.AddTable(‘Table 1’)
This might seem like a lot to take in, but fear not: the complete Silverlight Spy class library reference is available in the offline and online Silverlight Spy help, and a predefined set of DLR scripts is installed in the ($Install Folder)\DLR Scripts folder. Amongst those scripts are included demonstrations of how to list all databindings that are found in the user interface, how to query all dependency properties and so on.
.NET Reflector integration
The object browser in Silverlight Spy displays all .NET objects found in the assemblies of an application in a hierarchical manner, providing convenient access to assemblies, namespaces, types, resources, references, base types, etc. By default, the object browser lists all assemblies that are found in the XAP package, and when you right-click on the object browser node and select “Show All Assemblies”, all referenced core assemblies are listed as well.
As you’re no doubt aware, Silverlight Spy uses .NET Reflector for decompilation services. When Silverlight Spy has been configured to use Reflector, it provides the source code of a Silverlight application in any .NET language. Reflector can be easily configured in the options dialog (Tools > Options > Reflector), and once configured, the View pane displays the decompiled source of the selected object in the Object browser.
If you prefer to view the decompiled source in a standalone Reflector instance, you can right-click on the Object browser and assembly nodes and select “Open with Reflector…” to launch a Reflector instance with the Silverlight application assemblies preloaded.
The Resource dictionary node in the Explorer view provides direct access to all application, page and default resources that are found in the assemblies of the application. Using the Resource dictionary, one can easily extract the styles that are used by the application, and the content of the styles are rendered in the View pane when exploring the resource dictionary. Style extraction comes in very handy when you want to replicate the styles from an application!
The output log (accessible via View > Output Log) provides useful information about the internal working of Silverlight Spy. Information, warning and error messages are written to the output log, and come in handy when investigating any issues you might with the tool. The output trace level can be set in the options dialog (Tools > Options > General).
Unhandled exceptions that occur in the Silverlight applications you are inspecting are also written to this log view.
About Silverlight Spy
To wrap this all up, Silverlight Spy is a runtime inspector tool for Silverlight and Windows Phone applications. It is a commercial product created by First Floor Software, although a free edition is available as well, providing a limited but useful set of features for inspecting Silverlight applications.
For more details and to download Silverlight Spy, go to http://silverlightspy.com.