Inside PowerShell 3.0: Deep into the interpreter with .NET Reflector and Visual Studio 2012

So version 7.6 of .NET Reflector added Visual Studio 2012 integration. I’ve already been really excited by the new IDE as it dramatically reduced memory usage and just seems snappier over all. Additionally, it doesn’t upgrade csproj files so I can use it without breaking those still on VS2010. Now with the ability to step into third party source code, I’m getting a little too excited about all of this. I used Reflector to take apart PowerGUI but with 100% static code analysis. I wanted to write a post about how awesome debugging a third party assembly can be. So I figured…

It’s amazing how different code can look when you see it executing rather than when you are looking at it statically. I decided to play with the PowerShell Profiler project I made and step in from there. With some help from the RedGate guys I got System.Management.Automation to load un-optimized. Here is what I had to do:

For good measure I put an INI file in the GAC next to the System.Management.Automation.dll. Not sure if this is necessary or not but once I had it working I didn’t want to tweak it. ;)
A full outline of what needs to be done is contained in the RedGate post. Once this was done I loaded up Visual Studio and had to make a couple adjustments to the debugging properties.
In Debugging->General I turned off the following:
  • Just My Code
  • Require source files to exactly match the original version

The final step is to decompile the System.Management.Automation assembly. You can do this by clicking the .NET Reflector menu item and selecting Choose Assemblies to Debug. It took about 5-7 minutes to generate the debug information. Reflector automatically throws the “Debug Cache” folder into the list of symbol folders in the debugger settings. You’ll know it’s working when you look in the Modules window see that the System.Management.Automation assembly is not optimized.

Be careful. The next section is dangerous. 

So starting at the top of the call stack I worked my way down from the ScriptBlock into an internal “Interpreter” class. These are some of the interesting things I’ve run into. The ScriptBlock itself is abstract.

The real implementation I’ve seen used is the CompiledScriptBlock class. As it’s aptly named it is probably compiled. I set a break point right inside the Invoke method that is used to run a script block. If you notice we can access all the debugging information that we could with our own code. I have a simple “Get-Process” running in this example.

Once we have grabbed the current runspace we actually do the invoke. This involves creating a new Pipe and then invoking it.

We end up in the DlrScriptCommandProcessor class. It accepts an Action<FunctionContext> that is the clause that we are executing.
Next, we end up the in the LightLambda class. I would imagine that it is a lambda on a diet but I can’t know for sure. I would need to study it more. In the RunVoid1 method we actually hit the interpreter and have it run the current InterpretedFrame.

Inside the interpreter we take our current frame and iterate over the instructions in that frame. The instructions are then run. Here we can see what happens in a LoadFieldInstruction.

I actually see the interpreter called twice with two different frames. The second time through I noticed some more use of dynamics. After changing the script to a “Start-Process Notepad” it was obvious the second run through was the actual execution of the script block. The first execution may be initialization of some kind.

It is simply amazing how well I can step through the decompiled source code once everything is setup correctly. It feels like I’m debugging my own code. Oisin might be right…

What does this tell us about PowerShell execution? I am not smart enough to talk to that. What does it tell us about the PowerShell team? They are extremely smart. What does this tell me about myself? That I should probably find a new hobby.

 

You can leave a response, or trackback from your own site.

2 Responses to “Inside PowerShell 3.0: Deep into the interpreter with .NET Reflector and Visual Studio 2012”

  1. [...] Inside PowerShell 3.0: Deep into the interpreter with .NET Reflector and Visual Studio 2012 (Adam Driscoll) [...]

  2. sarabjeet says:

    Thanks for all the information,it was very helpful and i really like that you are providing information on .net training ,being enrolled in .net freshers training with projects live training http://www.wiziq.com/course/57-fresher-training-projects i was looking for such .net fresher training to assist me and your information helped me a lot.Really like that you are providing such information . Thanks.

Leave a Reply

In an effort to prevent automatic filling, you should perform a task displayed below.



four + = 10