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.