Click here to monitor SSC
  • Av rating:
  • Total votes: 16
  • Total comments: 20
Ben Hall

'Methodist': Make .NET Reflector come alive with IronPython

21 May 2009

It is great to be able to inspect the contents of an assembly with .NET Reflector, but to really understand the behaviour of code, it is nice to be able to call methods and see the results immediately within .NET Reflector. Now you can, thanks to the magic of IronPython and the DLR. Ben builds a REPL add-in for .NET Reflector and makes a great tool even more useful.

Anyone who has used .NET Reflector  knows what an amazing application it is! Being able to disassemble .Net objects into C# code: wow! Whereas it is useful to see the code, you can’t always fully understand the behaviour of code just from inspection. Wouldn’t it be great if you could see the code, and then initialize and interact with the object, calling methods and seeing the result directly within .NET Reflector?  Thanks to the Dynamic Language Runtime (DLR) and IronPython – you can!

This article will outline the functionality of a new add-in component called ‘Methodist’ that I’ve written, and will describe the advantages it beings to .NET Reflector. The article will then discuss the technical details of the add-in and show how it was made possible.

'Methodist'

'Methodist' plugs into the .NET Reflector infrastructure list like any other of its' add-ins, while, at the same time, hosting the DLR. This  allows the use of the Python language against objects loaded into the  .NET Reflector assembly browser.

The DLR is a new platform from Microsoft which is gaining a lot of well-deserved attention. The platform sits on top of the CLR and is designed to allow dynamic languages to be implemented within the .Net platform. This enables them to interact with everything that .net has to offer while at the same time allowing applications, such as .NET Reflector, to embed the platform and take advantage of the capabilities offered by dynamic languages.

Dynamic languages themselves are on the increase. Many different languages, such as JavaScript, Ruby and Python fall into the dynamic category. Each of these languages offers something different, but they all share in common the principle that everything is determined at runtime, whereas with static languages like C# almost everything is determined at compile time in order to make the language  more flexible.  A Dynamic Language REPL allows us to execute code as we type it. This means we no longer need to write code, compile, load and execute in order to see the result. Dynamic languages evaluate everything at runtime, so that the world the language knows about,  such as the methods that exist on objects, the accessible objects or the libraries that are loaded, can change. Because of this, you can adapt the lifecycle to your needs and circumstances. Dynamic languages also tend to be more readable. Because they infer a lot from the code, there is much less ‘noise’ required than other languages: For example, there is no need to define a type for a variable as this is simply inferred at execution. The result is easier to type and read code.

The DLR makes it possible to implement dynamic languages on top of the .Net framework that can then interop with .Net objects and assemblies in exactly the same way they would with their native objects and libraries. For me, this combines the best of both worlds: For others this means they don’t need to learn a new coding style and set of libraries.

We can take advantage of all of this via .NET Reflector.

Installing "Methodist"

To run "Methodist", first make sure you have the current version of Reflector installed. To install "Methodist", download the DEBUG.ZIP from the speech bubble at the top of the article, and copy the following files to the directory in wehich you installed Reflector.

  • IronPython.dll
  • IronPython.Modules.dll
  • Microsoft.Scripting.Core.dll
  • Microsoft.Scripting.dll
  • Microsoft.Scripting.ExtensionAttribute.dll
  • TheMethodist.dll

Start Reflector. Then click on the view->Addins menu and click on the Add button. In the dialog box that appears, select TheMethodist.DLL, and then close the dialog box. To see the methodist pane, click Cntl D. or use the tools menu

Using 'Methodist'

As you can see from the screenshot below, the add-in simply plugs into .NET Reflector and provides the user with a command style prompt to start typing and executing code (a REPL).

 Fig 1 The Command-style prompt

By way of an example, we can do simple things such as add numbers together. While the code looks easily, under the covers the code goes via the IronPython implementation, converted into the correct representation for the DLR before being passed to the CLR as Intermediate Language (IL) for execution. The result is 2, which is being displayed on screen.

Fig 2: First steps for the REPL

Yet the implementation provides more than just this. Within the .NET Reflector Assembly Browser we have various standard .Net 3.5 assemblies loaded.  Because they are already loaded into .NET Reflector, our Methodist add-in has already detected and loaded them into its own process.

We can now start creating instances of objects. System.Windows.Forms is the main assembly for WinForms, the UI framework for .Net 2.0. From our Methodist add-in , we can create and interact with a new Window, clicking buttons and causing events to fire.

Fig 3: Hello world!

This demonstrates how flexible you can be with IronPython and how you can use it to interact with .Net. However, the fact we have embedded the application into .NET Reflector makes this more useful. 

As I mentioned in the introduction, seeing the code is only part of the process when we want to understand what it does. In reality, the best way to learn how the object works is to actually use it. For example, Path has a number of really useful methods. Yet, understanding what they do just from the code is difficult. With the help of the  'Methodist' add-in , we can interact with the Path object in a live environment and see what they actually do and the results they return.

From System.IO import *
Path.Combine()
Path.GetTempFileName()
Path.GetTempPath()

fig 4: Ooh! Executing code within .NET Reflector!

This is a great way to understand how the objects work. The same concept can be applied to testing different inputs and seeing how the method behaves. A method I occasionally use is ExpandEnvironmentVariables, this takes a Environment variable such as %TEMP% and expands it to be the actual path. To ensure I am using the method correctly, I can use the 'Methodist' add-in with some different inputs to verify that my expectations about how the method behaves are correct.

Fig 5: Ah, so that is what the method does

By being able to interact with methods, it becomes much quicker to learn new frameworks and methods, but there are times when we cannot access a method or property because it is private or marked as internal. C# allows you to use reflection to gain access to these methods, but it can be a case of trail and error to find the correct property to use. With IronPython, together with the correct flags, this is not an issue. Take the DLRReflector.Sample assembly. The TestObj class has three methods, 1 public, 1 internal, and 1 private. With 'Methodist' add-in , we can create an instance of the object as normal.

from DLRReflector.Sample import *
t = TestObj()

We can then inspect the methods on the object using the dir command. This provides us with a list of all the methods we can call on the object.  Two of the methods listed are internal and private prefixed with the object name.  Now we know the names, we can call and interact with them like normal.

t._TestObj__Testing()
t._TestObj__PrivateMethod()

This is very useful if you really want to understand the implementation of the object.

DLRReflector.Sample
Dir(t)
t._TestObj__Testing()
t._TestObj__PrivateMethod()

Fig 6: '... useful if you really want to understand the implementation of the object'

Hopefully you can see how powerful having the DLR and .NET Reflector together can be. We can combine the power of .NET Reflector and being able to see the code with the ability to actually construct and interact with the objects – all from the same application!

How we built 'Methodist'

With the feature set in mind, we’ll now dive into the implementation and see how it was all put together. For an overview of Reflector add-ins, I recommend you read Andrew Clarke’s article (http://www.simple-talk.com/dotnet/.net-tools/using-.net-reflector-add-ins/).

DLRPackage.cs

Like with all Reflector extensions, we need an object which implements IPackage. This is the starting point for our add-in with the Load() method being the first method called by Reflector. The package is responsible for initialising our interaction with the DLR, creating the window, menu items and finally loading the assemblies into the DLR itself.

The initialisation of the Window is the main part of within our Load method. This allows users to display the add-in and start typing code. The first object required is the DLRHost, this is the object which is responsible for our hosting the DLR within our add-in.

DLRHost host = new DLRHost(ServiceProvider);

We provide this object as a parameter to our ConsoleWindowManager. This knows how to construct our user control and add a menu item to the toolbar. 

ConsoleWindowManager manager = new ConsoleWindowManager(serviceProvider, host);

            manager.CreateConsoleWindow();

            manager.AddToolbarItem();

In order to be able to display a window within Reflector, we need to register the window with the WindowManager.  This is done by accessing the IWindowManager service via the ServiceProvider and adding a new instance of our window, which is a simple WinForms UserControl.

  public void CreateConsoleWindow()

        {

            ConsoleWindow c = new ConsoleWindow(Host);

            windowManager = ( (IWindowManager)serviceProvider.GetService(typeof(IWindowManager));

 

            windowManager.Windows.Add("Console", c, "Methodist");

        }

Adding an item to the toolbar is done in a similar fashion via the ICommandBarManager service. The code below will add a separator together with a new button with the name Methodist under the Tools menu item. We have also attached a shortcut key of Ctrl+D.

    public void AddToolbarItem()

        {

            var commandBarManager = (ICommandBarManager)serviceProvider.GetService(typeof(ICommandBarManager));

            commandBarManager.CommandBars[s["Tools"].Items.AddSeparator();

 

            commandBarManager.CommandBars["Tools"].Items.AddButton("Methodist", new EventHandler(DisplayConsoleWindow), Keys.Control | Keys.D);

        }


When the menu item is clicked, or the shortcut key used, the DisplayConsoleWindow method is called. This simply sets the Visiblity of our Window to true.

windowManager.Windows["Console"].Visible = true;

The next stage of our DLRPackage is the ability to load the assemblies. The idea is that when you load an into Reflector, it is automatically loaded into the DLR runtime. However, Reflector also automatically has a set of assemblies loaded on startup which we will also need to load into DLR Addin on initialisation. This is done by simply iterating around the Asssemblies from the AssemblyManager and then loading them into the DLR via the Load method.

      public void LoadAssemblies()

      {

         foreach (IAssembly item in AssemblyManager.Assemblies)

         {

            LoadNewAssembly(item);

         }

      }

 

      private void LoadNewAssembly(IAssembly item)

      {

         Dlr.Load(item);

         LoadedAssemblies.Add(item);

      }

The loading process is executed on separate thread so we don’t lock our UI. Based on the Reflector assembly object, IAssembly, we need to expand the path for the assembly’s location as Reflector provides the path as ‘%SystemRoot%\Microsoft.net\Framework\v2.0.50727\mscorlib.dll’.

Once we have the correct path, we load it into the appdomain, and then into the engine runtime.

ThreadStart starter2 = delegate { Engine.Runtime.LoadAssembly(Assembly.LoadFile(Environment.ExpandEnvironmentVariables(item.Location))); };

new Thread(starter2).Start();

To be able to continue to load in assemblies as and when the user does, we hook into Reflector’s AssemblyManager AssemblyLoaded event.

AssemblyManager.AssemblyLoaded += assemblyManager_AssemblyLoaded;

We then follow a similar process, we loop around the assemblies and if we can’t already loaded it then we call the above method. This allows users to load in new assemblies into Reflector and automatically have access to them from the Methodist.

void assemblyManager_AssemblyLoaded(object sender, EventArgs e)

{

         foreach (IAssembly item in AssemblyManager.Assemblies)

         {

            if (!LoadedAssemblies.Contains(item))

            {

               LoadNewAssembly(item);

            }

         }

}

 

We now have our Console Window and we have our assemblies being loaded. In order to load the assemblies, we needed an IronPython Engine. This engine was created by the DLRHost object.

DLRHost.cs

Our DLRHost object is responsible for hosting the DLR and the execution of IronPython code. To create the engine we ask the Python object to provide one for us.

ScriptEngine engine = IronPython.Hosting.Python.CreateEngine();

We then need to create a ScriptScope object which will store our variables, methods and objects created.

ScriptScope Scope = Engine.CreateScope();

In order to execute code, we have an Execute method which takes a string as a parameter. We then need to create a ScriptSource object via the CreateScriptSourceFromString method and provide the code string as a parameter. We can then use this object to execute our code, providing it with the scope to use.

public string Execute(string code)

{

    ScriptSource source = Engine.CreateScriptSourceFromString(code, (code.Contains(Environment.NewLine)) ? SourceCodeKind.Statements : SourceCodeKind.InteractiveCode);

    object result = source.Execute(Scope);

 

 

            if (result == null)

               return string.Empty;

            else

               return result.ToString();

}

Our DLRHost can now execute IronPython code. However, we still need to provide a way to accept code from the user and know when to execute it. This is the role of the ConsoleWindow.

ConsoleWindow.cs

The ConsoleWindow is our UserControl which we added as a window via our ConsoleWindowManager.  The fundamental role is to take input from the user via a textbox. When the user presses enter, the code should be executed. The communication between the window and the DLRHost is done via an event which is fired when the enter key is pressed.

DLRHost.cs

While we can execute code, the implementation is far from complete. The first task after being able to execute code is to redirect the output.

Redirect Out

When executing code, the user can cause data to be outputted to either the standard output or the standard error output. For example, in C#, when you use the Console.Writeline() method the data is simply wrote to the StandardOutput. As it happens in a console application this is the command prompt.

      public void RedirectOut(TextWriter writer)

      {

         TextWriterStream textStreamWriter = new TextWriterStream(writer);

 

         Engine.Runtime.IO.SetOutput(textStreamWriter, writer);

         Engine.Runtime.IO.SetErrorOutput(textStreamWriter, writer);

         Console.SetOut(writer);

         Console.SetError(writer);

      }

This method is called from our ConsoleWindow and as an argument a TextBoxWriter object is passed in. TextBoxWriter object inherits from TextWriter, however everything which is wrote to the stream is actually wrote out to the TextBox and as such our add-in instead. 

Continuations

At the moment, users can enter a single line of code and have it executed. This is fine for executing code such as 1+1, however if we want to define methods like our buttonClicked event then we need support for entering multiple lines of code.

To allow this, there is the concept of continuations. When the user enters code we need detect if they have only entered part of a statement. If they have, we need to prompt them to enter more code before we can execute.

To detect if the code is incomplete, we can access the Code Properties on the ScriptSource object.

      public bool PromptForContinuation(string code)

      {

         ScriptSource s = Engine.CreateScriptSourceFromString(code, SourceCodeKind.Statements);

         if (!IsComplete(s.GetCodeProperties(Engine.GetCompilerOptions())))

            return true;e;

         else

            return false;

      }

The result of the CodeProperties is a ScriptCodeParseResult. The GetCodeProperties method parses the code and then returns a result saying if the code is complete, invalid, or partially complete.  

      private bool IsComplete(ScriptCodeParseResult result)

      {

         if (result == ScriptCodeParseResult.IncompleteStatement

            || result == ScriptCodeParseResult.IncompleteToken

            || result == ScriptCodeParseResult.Invalid)

            return false;e;

         else

            return true;

     }

When it comes to the execution, we use this method to determine if we should prompt the user to enter additional code. If we should, then we set a flag and write out a continuation marker in the UI – this is the ‘.’ you can see in the screenshots above.

       public void Execute(string code)

        {

          codeContinuation += code;

 

           if (host.PromptForContinuation(codeContinuation))

           {

              inContinuation = true;

              WriteContinuation(););

           }

           else

           {

              inContinuation = false;

              host.Execute(codeContinuation);

              codeContinuation = string.Empty;

           }

        }

When we execute the code again, we add the newly entered snippet to what we already know about and see if it is complete. If it is, we execute normally.; If not we prompt for more code.

This section of code allows users to define their own methods to use during execution.

PrivateBinding

To allow access to internal and private methods and members, we need to set the PrivateBinding flag.

Setting engine flags needs to be done when you initialised the Engine. In our DLRHost constructor, we change the code to pass in the options as a property dictionary.

  IDictionary<string, object> options = new Dictionary<string, object>();

  options.Add("PrivateBinding", true);

  ScriptEngine engine = IronPython.Hosting.Python.CreateEngine(options);

When the engine is created, it will take these options into account and enable PrivateBinding allowing us to access the private methods.

Context Menu on Namespaces

Finally, after developing the add-in and using it in my day-to-day development I decided I wanted an easier way to import namespaces. Thankfully, Reflector allows us to extend the context menu based on the type of object the user clicked on.  This means we can add a new context menu onto our namespaces but leave the other objects untouched.

The AddContextMenu adds the item, when the user clicks the menu item the importIntoDLR method is called.

 public void AddContextMenu()

     {

     var commandBarManager = (ICommandBarManager)serviceProvider.GetService(typeof(ICommandBarManager));

     ICommandBarButton subMenu = commandBarManager.CommandBars["Browser.Namespace"].Items.AddButton("Import into Methodist", importIntoDLR);

     }

This method obtains the AssemblyBrowser, this allows us to determine which item is currently selected. Because we know this can only be called on Namespaces items we can cast the selected item to an INamespace and pass it to the ConsoleWindow object to write out the import statement.

 

 private void importIntoDLR(object sender, EventArgs e)

      {

         if (c != null)

         {

            var assemblyBrowser = (IAssemblyBrowser)serviceProvider.GetService(typeof(IAssemblyBrowser));

 

            c.WriteImport(assemblyBrowser.ActiveItem as INamespace);

            SetWindowVisability(true););

         }

      }

       public void WriteImport(INamespace item)

       {

          if (item == null) return;

          Output.Write(string.Format("from {0} import *", item.Name));

       }

While it is a simple change, it speeds up the process of interacting with objects.

Summary

'Methodist' is a new add-in for Reflector. It allows you to interact with objects within the live environment of Reflector. By hosting the DLR and providing you with the ability to write IronPython code, I feel this takes what is already great able reflector and extends it to add a new dimension and set of capabilities.

We would love to hear your comments on this, please leave them below.

 

Ben Hall

Author profile:

Ben Hall MVP is a UK C# developer/tester who enjoys all aspects of the development lifecycle and technology in general. During the day Ben works for Red Gate Software as a Test Engineer. At night, Ben is a MbUnit Core Commit Member, helping out on the project whenever possible. Ben has also gained his Microsoft Certified Technology Specialist (MCTS) in Web Applications and is a Microsoft Certified Professional (MCP) in Administrating Windows XP. He blogs on http://blog.benhall.me.uk/index.html He was awarded an MVP on July 2nd 2008 for "extraordinary efforts in Visual C# technical communities during the past year."

Search for other articles by Ben Hall

Rate this article:   Avg rating: from a total of 16 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: kens
Posted by: Anonymous (not signed in)
Posted on: Monday, May 25, 2009 at 10:16 PM
Message: goodgoodgoodgood

Subject: Great work!
Posted by: Andreas Hallberg (not signed in)
Posted on: Tuesday, May 26, 2009 at 2:09 AM
Message: Ben, this is very useful. Thanks a lot! If you're working on adding more features you might want to consider command memory (arrow up cycles through the old commands) and adjusting font size/color.


Subject: Thanx
Posted by: odalet (view profile)
Posted on: Tuesday, May 26, 2009 at 3:11 AM
Message: Very good! Played a little with it, and I adopted it.

For a Vnext, maybe incorporating a free text editor (#develop or scite) would provide better ux when editing code... But hey! You provide source code! I could try this... Do you have a specific license attached to your code? A codeplex project?

Thanks again for your app.

Subject: Crash
Posted by: Louis Somers (view profile)
Posted on: Tuesday, May 26, 2009 at 3:13 AM
Message: I have a crash when adding the plugin.
using .Net reflector 5.1.5.0
It doesn't give a nice .net tracefile that I can post here (I do have a 160Mb hdmp file).

I have most plugins from CodePlex installed, probably a conflict with one of those?

It looks verry helpfull though, looking forward to getting it work on my system!

Subject: Codeplex and Crash
Posted by: Andrew Clarke (view profile)
Posted on: Tuesday, May 26, 2009 at 3:40 AM
Message: Yes, we will be putting the project on the Reflector add-in site on Codeplex very soon, probably this week.
The add-in works fine on 5.1.5.0 on Simple-Talk's Editorial PCs I tested it on. There are several add-ins in place as well. It might be worth trying a separate installation with just Methodist to see if it is an add-in conflict.

Editor.

Subject: Inspirational!
Posted by: Jacques (not signed in)
Posted on: Tuesday, May 26, 2009 at 6:22 AM
Message: This might become one of the most useful add-ins.

A nice future feature will be automatic integration with a mocking framework - since a lot of code can't be executed in a few lines without mocking some dependencies.

Subject: Crash
Posted by: Anonymous (not signed in)
Posted on: Tuesday, May 26, 2009 at 6:47 AM
Message: I also have 5.1.5.0 installed and it crashes when I attempt to load it. I am running on Win7 Beta 1 x64

Subject: Crash as well
Posted by: Anonymous (not signed in)
Posted on: Tuesday, May 26, 2009 at 7:18 AM
Message: 5.1.5.0
Crashes when I add the plugin
No other add-ins installed.

Subject: Great Article / Crash
Posted by: Oliver (not signed in)
Posted on: Tuesday, May 26, 2009 at 7:35 AM
Message: Hi, your article really did whet my appetite!
Five stars from me.

Methodist crashes on me immediately when i add the plugin.

Reflector version: 5.1.5.0
Plugins: no other add-ins installed
OS: Win XP Prof. SP3 with Microsoft Updates
.NET 3.5 SP1

Subject: Works great on Win 2003 R2 SP2
Posted by: Oliver (not signed in)
Posted on: Tuesday, May 26, 2009 at 8:34 AM
Message: Hi,

this time, i have tried Methodist on one of my virtual servers: works like a charm!

Reflector version: 5.1.5.0
Other Plugins: Snippy
OS: Windows Server 2003 R2 Standard Edition SP2 (english, 32 bit, with Microsoft Updates)
.NET 3.5 SP1
Visual Studio 2008 Prof. (english)


Probably a language related problem or a missing dependency...


Cheers, Oliver

Subject: Crash
Posted by: Ben Hall (not signed in)
Posted on: Tuesday, May 26, 2009 at 10:21 AM
Message: Hi everyone,

I'm pleased you all like the idea\concept and I'm sorry that you are experiencing some issues.

I'll do some debugging and let you know what I find...

Thanks

Ben

Subject: Playing with objects to see what they do
Posted by: Dave M (view profile)
Posted on: Tuesday, May 26, 2009 at 11:14 AM
Message: I agree 100% with your comments about experimenting with objects to see what they do what input they accept and what causes them to break.

Not that you need reflector to do this. We have had this ability in C#, VB.Net, VB6 etc. for years in the debugger Immediate Window. I kind of took this functionality for granted until I recently demonstrated it to a very competent C# programmer who had not seen it before - could be more of an old VB programmer thing as the habit was well established in VB6.

You can also use this functionality with stand-alone JavaScript if you use the Visual Sudio debugger to debug JavaScript code - presumably for VBScript too, but I have never tried it.

The add-in looks great.

Dave M

Subject: New Build
Posted by: Ben Hall (not signed in)
Posted on: Tuesday, May 26, 2009 at 11:53 AM
Message: We have uploaded a new build on the addin which you can download from the link at the top - http://www.simple-talk.com/content/file.ashx?file=1964

Hopefully this should solve any problems you have been experiencing - if not then please let us know. Note, the addin, together with IronPython and the DLR needs to be in the same directory.

I've also updated the font to hopefully make it a little more readable :)


Keep the feedback coming!

Subject: crash
Posted by: dantorbz (not signed in)
Posted on: Tuesday, May 26, 2009 at 7:17 PM
Message: it seems the new build still crashes reflector whenever adding the plugin when there're assemblies already loaded in reflector. doesn't crash otherwise.

OS same spec as above: OS: Win XP Prof. SP3 with Microsoft Updates
.NET 3.5 SP1

Subject: Sweet
Posted by: Greg Bray (not signed in)
Posted on: Wednesday, May 27, 2009 at 12:10 PM
Message: Very cool! I can see this being quite useful. Here is some quick feedback after playing around with it for a bit:

1. The console input needs a bit of work. Right now you can't cancel an input statement or reset the IronPython console state if you mess up. If you type something like Import * and then press enter you have to close Reflector to get the console working again. A blank line or line with only space/tabs should cause it to finish the current statement, validate it, display an error if it is incorrect, and then move to the next. The CommandBuffer built into IronPython Studio seems to work pretty well, so you might want to checkout their code at http://ironpythonstudio.codeplex.com/SourceControl/changeset/view/9636#69576

2. Code completion and call tips would be awesome! The IronPython Studio console is a pretty good example, but they use the Visual Studio Source object CodeWindowManager so it probably can't be replicated in Reflector. You might be able to use the docstring code from this site to help get things started: http://www.voidspace.org.uk/python/weblog/arch_d7_2009_05_16.shtml#e1090

Subject: Thanks
Posted by: Ben Hall (not signed in)
Posted on: Thursday, May 28, 2009 at 3:24 PM
Message: @Greg Bray

Thanks for the feedback! Both are great suggestions. Hopefully there will be a v2 where I can improve the console input and look at adding additional functionality.

Ben

Subject: dynamic languages
Posted by: Anonymous (not signed in)
Posted on: Sunday, May 31, 2009 at 3:47 PM
Message: > dynamic languages also tend to be more readable.

Nonsense

Subject: Crash
Posted by: Eric (view profile)
Posted on: Sunday, May 31, 2009 at 8:22 PM
Message: The AddIn was crashing Reflector (No others AddIns, own List defined). I need to delete the Reflector.cfg. Then it was working.

Subject: Delete Reflector.cfg works
Posted by: Anonymous (not signed in)
Posted on: Tuesday, June 02, 2009 at 12:38 AM
Message: Hi Eric, I tried to delete the Reflector.cfg. It is working. Thanks.

Really cool AddIn.

Subject: more defense from crashes
Posted by: dantorbz (view profile)
Posted on: Sunday, June 07, 2009 at 6:04 PM
Message: removing .cfg doesn't solve the root cause. it works until you load more assemblies, then the plugin crashes reflector again.

i've tried to add more defensive coding into the plugin, by adding try-catch to DLRHost.Load delegate and now reflector doesn't crash:

try
{
.....
(Assembly.LoadFile(Environment.ExpandEnvironmentVariables(item.Location)));
ThreadStart starter2 = delegate
{
try
{
Engine.Runtime.LoadAssembly(
Assembly.LoadFile(Environment.ExpandEnvironmentVariables(item.Location)));
}
catch (Exception ex)
{
Console.Error.WriteLine("Unable to load assembly: " + item.Location);
}
};
new Thread(starter2).Start();
}

 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.