Home > Software engineering >  How to find the current module in the DebuggerStop event handler?
How to find the current module in the DebuggerStop event handler?

Time:08-22

I work on a PowerShell debugger implemented as a script, Add-Debugger.ps1. It looks peculiar perhaps but there are use cases for it.

All works well except when the debugger stops at a breakpoint in a script module. One of the debugger functions is to execute interactively typed user commands and show results. The problem is that these commands are not invoked in the current script module scope but "somewhere else".

The problem may be worked around if the current module is known, say $module. Then commands invoked as $module.Invoke() would work in the module scope. But how to find/get this $module? That is the question.

NB $ExecutionContext.SessionState.Module does not seem to help, even if I get it using Get-Variable -Scope 1. Because $ExecutionContext is for the DebuggerStop handler, not its parent in the module. And Get-Variable is invoked "somewhere else" and does not get variables from the module.

CodePudding user response:

I have found a workaround using this dynamically compiled piece of C#:

Add-Type @'
using System;
using System.Management.Automation;
public class AddDebuggerHelpers
{
    public ScriptBlock DebuggerStopProxy;
    public EventHandler<DebuggerStopEventArgs> DebuggerStopHandler { get { return OnDebuggerStop; } }
    void OnDebuggerStop(object sender, DebuggerStopEventArgs e)
    {
        SessionState state = ((EngineIntrinsics)ScriptBlock.Create("$ExecutionContext").Invoke()[0].BaseObject).SessionState;
        state.InvokeCommand.InvokeScript(false, DebuggerStopProxy, null, state.Module, e);
    }
}
'@

It works and gives me the $module that I needed. By the way, for my particular task I use it as $module.NewBoundScriptBlock(...) instead of mentioned $module.Invoke(...), to preserve the current scope.

If another native PowerShell way without C# is found and posted, I'll accept it as an answer even after accepting my own. Otherwise this workaround is the only known way so far.

  • Related