mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Add APIs for breakpoint management in runspaces and enable attach to process without BreakAll for PSES (#10338)
This commit is contained in:
committed by
Aditya Patwardhan
parent
cfdbd71888
commit
cc0fed479a
@@ -101,19 +101,11 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The optional breakpoint objects to use for debugging.
|
||||
/// Gets or sets a flag that tells PowerShell to automatically perform a BreakAll when the debugger is attached to the remote target.
|
||||
/// </summary>
|
||||
[Experimental("Microsoft.PowerShell.Utility.PSDebugRunspaceWithBreakpoints", ExperimentAction.Show)]
|
||||
[Parameter(Position = 1,
|
||||
ParameterSetName = DebugRunspaceCommand.InstanceIdParameterSet)]
|
||||
[Parameter(ParameterSetName = DebugRunspaceCommand.RunspaceParameterSet)]
|
||||
[Parameter(ParameterSetName = DebugRunspaceCommand.IdParameterSet)]
|
||||
[Parameter(ParameterSetName = DebugRunspaceCommand.NameParameterSet)]
|
||||
public Breakpoint[] Breakpoint
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
[Experimental("Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace", ExperimentAction.Show)]
|
||||
[Parameter]
|
||||
public SwitchParameter BreakAll { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -275,7 +267,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
_debugger.SetDebugMode(DebugModes.LocalScript | DebugModes.RemoteScript);
|
||||
|
||||
// Set up host script debugger to debug the runspace.
|
||||
_debugger.DebugRunspace(_runspace, disableBreakAll: Breakpoint?.Length > 0);
|
||||
_debugger.DebugRunspace(_runspace, breakAll: BreakAll);
|
||||
|
||||
while (_debugging)
|
||||
{
|
||||
@@ -532,10 +524,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
SetLocalMode(runspace.Debugger, true);
|
||||
EnableHostDebugger(runspace, false);
|
||||
if (Breakpoint?.Length > 0)
|
||||
{
|
||||
runspace.Debugger?.SetBreakpoints(Breakpoint);
|
||||
}
|
||||
}
|
||||
|
||||
private void RestoreRunspace(Runspace runspace)
|
||||
|
||||
-22
@@ -350,22 +350,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the optional breakpoint objects to use for debugging.
|
||||
/// </summary>
|
||||
[Experimental("Microsoft.PowerShell.Utility.PSDebugRunspaceWithBreakpoints", ExperimentAction.Show)]
|
||||
[Parameter(Position = 1,
|
||||
ParameterSetName = CommonRunspaceCommandBase.RunspaceParameterSet)]
|
||||
[Parameter(Position = 1,
|
||||
ParameterSetName = CommonRunspaceCommandBase.RunspaceNameParameterSet)]
|
||||
[Parameter(Position = 1,
|
||||
ParameterSetName = CommonRunspaceCommandBase.RunspaceIdParameterSet)]
|
||||
public Breakpoint[] Breakpoint
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
@@ -428,12 +412,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
debugger.SetDebuggerStepMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
// If any breakpoints were provided, set those in the debugger.
|
||||
if (Breakpoint?.Length > 0)
|
||||
{
|
||||
debugger.SetBreakpoints(Breakpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Internal;
|
||||
|
||||
namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// This class implements New-PSBreakpoint command.
|
||||
/// </summary>
|
||||
[Experimental("Microsoft.PowerShell.Utility.PSDebugRunspaceWithBreakpoints", ExperimentAction.Show)]
|
||||
[Cmdlet(VerbsCommon.New, "PSBreakpoint", DefaultParameterSetName = LineParameterSetName, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=113449")]
|
||||
[OutputType(typeof(VariableBreakpoint), typeof(CommandBreakpoint), typeof(LineBreakpoint))]
|
||||
public class NewPSBreakpointCommand : PSBreakpointCreationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new breakpoint.
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
// If there is a script, resolve its path
|
||||
Collection<string> scripts = ResolveScriptPaths();
|
||||
|
||||
// If it is a command breakpoint...
|
||||
if (ParameterSetName.Equals(CommandParameterSetName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
for (int i = 0; i < Command.Length; i++)
|
||||
{
|
||||
if (scripts.Count > 0)
|
||||
{
|
||||
foreach (string path in scripts)
|
||||
{
|
||||
WildcardPattern pattern = WildcardPattern.Get(Command[i], WildcardOptions.Compiled | WildcardOptions.IgnoreCase);
|
||||
WriteObject(new CommandBreakpoint(path, pattern, Command[i], Action));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WildcardPattern pattern = WildcardPattern.Get(Command[i], WildcardOptions.Compiled | WildcardOptions.IgnoreCase);
|
||||
WriteObject(new CommandBreakpoint(null, pattern, Command[i], Action));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ParameterSetName.Equals(VariableParameterSetName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// If it is a variable breakpoint...
|
||||
for (int i = 0; i < Variable.Length; i++)
|
||||
{
|
||||
if (scripts.Count > 0)
|
||||
{
|
||||
foreach (string path in scripts)
|
||||
{
|
||||
WriteObject(new VariableBreakpoint(path, Variable[i], Mode, Action));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObject(new VariableBreakpoint(null, Variable[i], Mode, Action));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else it is the default parameter set (Line breakpoint)...
|
||||
Debug.Assert(ParameterSetName.Equals(LineParameterSetName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
for (int i = 0; i < Line.Length; i++)
|
||||
{
|
||||
if (Line[i] < 1)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
new ArgumentException(Debugger.LineLessThanOne),
|
||||
"NewPSBreakpoint:LineLessThanOne",
|
||||
ErrorCategory.InvalidArgument,
|
||||
null));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (string path in scripts)
|
||||
{
|
||||
if (Column != 0)
|
||||
{
|
||||
WriteObject(new LineBreakpoint(path, Line[i], Column, Action));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObject(new LineBreakpoint(path, Line[i], Action));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,13 +75,13 @@ namespace Microsoft.PowerShell.Commands
|
||||
foreach (string path in scripts)
|
||||
{
|
||||
WriteObject(
|
||||
Context.Debugger.NewCommandBreakpoint(path.ToString(), Command[i], Action));
|
||||
Context.Debugger.SetCommandBreakpoint(Command[i], Action, path));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObject(
|
||||
Context.Debugger.NewCommandBreakpoint(Command[i], Action));
|
||||
Context.Debugger.SetCommandBreakpoint(Command[i], Action));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,13 +97,13 @@ namespace Microsoft.PowerShell.Commands
|
||||
foreach (string path in scripts)
|
||||
{
|
||||
WriteObject(
|
||||
Context.Debugger.NewVariableBreakpoint(path.ToString(), Variable[i], Mode, Action));
|
||||
Context.Debugger.SetVariableBreakpoint(Variable[i], Mode, Action, path));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObject(
|
||||
Context.Debugger.NewVariableBreakpoint(Variable[i], Mode, Action));
|
||||
Context.Debugger.SetVariableBreakpoint(Variable[i], Mode, Action));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,16 +130,8 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
foreach (string path in scripts)
|
||||
{
|
||||
if (Column != 0)
|
||||
{
|
||||
WriteObject(
|
||||
Context.Debugger.NewStatementBreakpoint(path, Line[i], Column, Action));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteObject(
|
||||
Context.Debugger.NewLineBreakpoint(path, Line[i], Action));
|
||||
}
|
||||
WriteObject(
|
||||
Context.Debugger.SetLineBreakpoint(path, Line[i], Column, Action));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ CmdletsToExport = @(
|
||||
'Set-MarkdownOption', 'Add-Member', 'Get-Member', 'Compare-Object', 'Group-Object', 'Measure-Object',
|
||||
'New-Object', 'Select-Object', 'Sort-Object', 'Tee-Object', 'Register-ObjectEvent', 'Write-Output',
|
||||
'Import-PowerShellDataFile', 'Write-Progress', 'Disable-PSBreakpoint', 'Enable-PSBreakpoint',
|
||||
'Get-PSBreakpoint', 'Remove-PSBreakpoint', 'Set-PSBreakpoint', 'New-PSBreakpoint', 'Get-PSCallStack', 'Export-PSSession',
|
||||
'Get-PSBreakpoint', 'Remove-PSBreakpoint', 'Set-PSBreakpoint', 'Get-PSCallStack', 'Export-PSSession',
|
||||
'Import-PSSession', 'Get-Random', 'Invoke-RestMethod', 'Debug-Runspace', 'Get-Runspace',
|
||||
'Disable-RunspaceDebug', 'Enable-RunspaceDebug', 'Get-RunspaceDebug', 'Start-Sleep', 'Join-String',
|
||||
'Out-String', 'Select-String', 'ConvertFrom-StringData', 'Format-Table', 'New-TemporaryFile', 'New-TimeSpan',
|
||||
@@ -35,8 +35,8 @@ PrivateData = @{
|
||||
PSData = @{
|
||||
ExperimentalFeatures = @(
|
||||
@{
|
||||
Name = 'Microsoft.PowerShell.Utility.PSDebugRunspaceWithBreakpoints'
|
||||
Description = "Enables the New-PSBreakpoint cmdlet and the -Breakpoint parameter on Debug-Runspace to set breakpoints in another Runspace upfront."
|
||||
Name = 'Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace'
|
||||
Description = 'Enables -BreakAll parameter on Debug-Runspace and Debug-Job cmdlets to allow users to decide if they want PowerShell to break immediately in the current location when they attach a debugger.'
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ CmdletsToExport = @(
|
||||
'Show-Markdown', 'Get-MarkdownOption', 'Set-MarkdownOption', 'Add-Member', 'Get-Member', 'Compare-Object', 'Group-Object',
|
||||
'Measure-Object', 'New-Object', 'Select-Object', 'Sort-Object', 'Tee-Object', 'Register-ObjectEvent', 'Write-Output',
|
||||
'Import-PowerShellDataFile', 'Write-Progress', 'Disable-PSBreakpoint', 'Enable-PSBreakpoint', 'Get-PSBreakpoint',
|
||||
'Remove-PSBreakpoint', 'Set-PSBreakpoint', 'New-PSBreakpoint', 'Get-PSCallStack', 'Export-PSSession', 'Import-PSSession', 'Get-Random',
|
||||
'Remove-PSBreakpoint', 'Set-PSBreakpoint', 'Get-PSCallStack', 'Export-PSSession', 'Import-PSSession', 'Get-Random',
|
||||
'Invoke-RestMethod', 'Debug-Runspace', 'Get-Runspace', 'Disable-RunspaceDebug', 'Enable-RunspaceDebug',
|
||||
'Get-RunspaceDebug', 'ConvertFrom-SddlString', 'Start-Sleep', 'Join-String', 'Out-String', 'Select-String',
|
||||
'ConvertFrom-StringData', 'Format-Table', 'New-TemporaryFile', 'New-TimeSpan', 'Get-TraceSource', 'Set-TraceSource',
|
||||
@@ -29,4 +29,14 @@ FunctionsToExport = @()
|
||||
AliasesToExport = @('fhx')
|
||||
NestedModules = @("Microsoft.PowerShell.Commands.Utility.dll")
|
||||
HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=855960'
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
ExperimentalFeatures = @(
|
||||
@{
|
||||
Name = 'Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace'
|
||||
Description = 'Enables -BreakAll parameter on Debug-Runspace and Debug-Job cmdlets to allow users to decide if they want PowerShell to break immediately in the current location when they attach a debugger.'
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4545,7 +4545,6 @@ end {
|
||||
new SessionStateAliasEntry("mi", "Move-Item", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("mp", "Move-ItemProperty", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("nal", "New-Alias", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("nbp", "New-PSBreakpoint", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("ndr", "New-PSDrive", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("ni", "New-Item", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("nv", "New-Variable", string.Empty, ReadOnly),
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace System.Management.Automation
|
||||
private static readonly SemanticVersion s_psV6Version = new SemanticVersion(6, 0, 0, preReleaseLabel: null, buildLabel: null);
|
||||
private static readonly SemanticVersion s_psV61Version = new SemanticVersion(6, 1, 0, preReleaseLabel: null, buildLabel: null);
|
||||
private static readonly SemanticVersion s_psV62Version = new SemanticVersion(6, 2, 0, preReleaseLabel: null, buildLabel: null);
|
||||
private static readonly SemanticVersion s_psV7Version = new SemanticVersion(7, 0, 0, preReleaseLabel: null, buildLabel: null);
|
||||
private static readonly SemanticVersion s_psSemVersion;
|
||||
private static readonly Version s_psVersion;
|
||||
|
||||
@@ -329,6 +330,11 @@ namespace System.Management.Automation
|
||||
get { return s_psV6Version; }
|
||||
}
|
||||
|
||||
internal static SemanticVersion PSV7Version
|
||||
{
|
||||
get { return s_psV7Version; }
|
||||
}
|
||||
|
||||
internal static SemanticVersion PSCurrentVersion
|
||||
{
|
||||
get { return s_psSemVersion; }
|
||||
|
||||
@@ -128,9 +128,7 @@ namespace System.Management.Automation
|
||||
return BreakpointAction.Continue;
|
||||
}
|
||||
|
||||
internal virtual void RemoveSelf(ScriptDebugger debugger)
|
||||
{
|
||||
}
|
||||
internal virtual bool RemoveSelf(ScriptDebugger debugger) => false;
|
||||
|
||||
#endregion methods
|
||||
|
||||
@@ -208,10 +206,8 @@ namespace System.Management.Automation
|
||||
: StringUtil.Format(DebuggerStrings.CommandBreakpointString, Command);
|
||||
}
|
||||
|
||||
internal override void RemoveSelf(ScriptDebugger debugger)
|
||||
{
|
||||
internal override bool RemoveSelf(ScriptDebugger debugger) =>
|
||||
debugger.RemoveCommandBreakpoint(this);
|
||||
}
|
||||
|
||||
private bool CommandInfoMatches(CommandInfo commandInfo)
|
||||
{
|
||||
@@ -350,10 +346,8 @@ namespace System.Management.Automation
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override void RemoveSelf(ScriptDebugger debugger)
|
||||
{
|
||||
internal override bool RemoveSelf(ScriptDebugger debugger) =>
|
||||
debugger.RemoveVariableBreakpoint(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -589,7 +583,7 @@ namespace System.Management.Automation
|
||||
this.BreakpointBitArray.Set(SequencePointIndex, true);
|
||||
}
|
||||
|
||||
internal override void RemoveSelf(ScriptDebugger debugger)
|
||||
internal override bool RemoveSelf(ScriptDebugger debugger)
|
||||
{
|
||||
if (this.SequencePoints != null)
|
||||
{
|
||||
@@ -612,7 +606,7 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
debugger.RemoveLineBreakpoint(this);
|
||||
return debugger.RemoveLineBreakpoint(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,31 +618,74 @@ namespace System.Management.Automation
|
||||
return new Collection<CallStackFrame>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the provided set of breakpoints to the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoints">Breakpoints.</param>
|
||||
public virtual void SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
|
||||
{
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a breakpoint by id, primarily for Enable/Disable/Remove-PSBreakpoint cmdlets.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the breakpoint you want.</param>
|
||||
public virtual Breakpoint GetBreakpoint(int id)
|
||||
{
|
||||
public virtual Breakpoint GetBreakpoint(int id) =>
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns breakpoints primarily for the Get-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
public virtual List<Breakpoint> GetBreakpoints()
|
||||
{
|
||||
public virtual List<Breakpoint> GetBreakpoints() =>
|
||||
throw new PSNotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Sets a command breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="command">The name of the command that will trigger the breakpoint. This value is required and may not be null.</param>
|
||||
/// <param name="action">The action to take when the breakpoint is hit. If null, PowerShell will break into the debugger when the breakpoint is hit.</param>
|
||||
/// <param name="path">The path to the script file where the breakpoint may be hit. If null, the breakpoint may be hit anywhere the command is invoked.</param>
|
||||
/// <returns>The command breakpoint that was set.</returns>
|
||||
public virtual CommandBreakpoint SetCommandBreakpoint(string command, ScriptBlock action = null, string path = null) =>
|
||||
throw new PSNotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Sets a line breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the script file where the breakpoint may be hit. This value is required and may not be null.</param>
|
||||
/// <param name="line">The line in the script file where the breakpoint may be hit. This value is required and must be greater than or equal to 1.</param>
|
||||
/// <param name="column">The column in the script file where the breakpoint may be hit. If 0, the breakpoint will trigger on any statement on the line.</param>
|
||||
/// <param name="action">The action to take when the breakpoint is hit. If null, PowerShell will break into the debugger when the breakpoint is hit.</param>
|
||||
/// <returns>The line breakpoint that was set.</returns>
|
||||
public virtual LineBreakpoint SetLineBreakpoint(string path, int line, int column = 0, ScriptBlock action = null) =>
|
||||
throw new PSNotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Sets a variable breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="variableName">The name of the variable that will trigger the breakpoint. This value is required and may not be null.</param>
|
||||
/// <param name="accessMode">The variable access mode that will trigger the breakpoint. By default variable breakpoints will trigger only when the variable is updated.</param>
|
||||
/// <param name="action">The action to take when the breakpoint is hit. If null, PowerShell will break into the debugger when the breakpoint is hit.</param>
|
||||
/// <param name="path">The path to the script file where the breakpoint may be hit. If null, the breakpoint may be hit anywhere the variable is accessed using the specified access mode.</param>
|
||||
/// <returns>The variable breakpoint that was set.</returns>
|
||||
public virtual VariableBreakpoint SetVariableBreakpoint(string variableName, VariableAccessMode accessMode = VariableAccessMode.Write, ScriptBlock action = null, string path = null) =>
|
||||
throw new PSNotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Removes a breakpoint from the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoint">The breakpoint to remove from the debugger. This value is required and may not be null.</param>
|
||||
/// <returns>True if the breakpoint was removed from the debugger; false otherwise.</returns>
|
||||
public virtual bool RemoveBreakpoint(Breakpoint breakpoint) =>
|
||||
throw new PSNotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Enables a breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoint">The breakpoint to enable in the debugger. This value is required and may not be null.</param>
|
||||
/// <returns>The updated breakpoint if it was found; null if the breakpoint was not found in the debugger.</returns>
|
||||
public virtual Breakpoint EnableBreakpoint(Breakpoint breakpoint) =>
|
||||
throw new PSNotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Disables a breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoint">The breakpoint to enable in the debugger. This value is required and may not be null.</param>
|
||||
/// <returns>The updated breakpoint if it was found; null if the breakpoint was not found in the debugger.</returns>
|
||||
public virtual Breakpoint DisableBreakpoint(Breakpoint breakpoint) =>
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the command processor source information so that it is
|
||||
@@ -704,13 +747,15 @@ namespace System.Management.Automation
|
||||
/// Sets up debugger to debug provided job or its child jobs.
|
||||
/// </summary>
|
||||
/// <param name="job">
|
||||
/// Job object that is either a debuggable job or a container
|
||||
/// of debuggable child jobs.
|
||||
/// Job object that is either a debuggable job or a container of
|
||||
/// debuggable child jobs.
|
||||
/// </param>
|
||||
internal virtual void DebugJob(Job job)
|
||||
{
|
||||
/// <param name="breakAll">
|
||||
/// If true, the debugger automatically invokes a break all when it
|
||||
/// attaches to the job.
|
||||
/// </param>
|
||||
internal virtual void DebugJob(Job job, bool breakAll) =>
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes job from debugger job list and pops the its
|
||||
@@ -763,21 +808,15 @@ namespace System.Management.Automation
|
||||
/// <summary>
|
||||
/// Sets up debugger to debug provided Runspace in a nested debug session.
|
||||
/// </summary>
|
||||
/// <param name="runspace">Runspace to debug.</param>
|
||||
internal virtual void DebugRunspace(Runspace runspace)
|
||||
{
|
||||
/// <param name="runspace">
|
||||
/// The runspace to debug.
|
||||
/// </param>
|
||||
/// <param name="breakAll">
|
||||
/// If true, the debugger automatically invokes a break all when it
|
||||
/// attaches to the runspace.
|
||||
/// </param>
|
||||
internal virtual void DebugRunspace(Runspace runspace, bool breakAll) =>
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up debugger to debug provided Runspace in a nested debug session.
|
||||
/// </summary>
|
||||
/// <param name="runspace">Runspace to debug.</param>
|
||||
/// <param name="disableBreakAll"></param>
|
||||
internal virtual void DebugRunspace(Runspace runspace, bool disableBreakAll)
|
||||
{
|
||||
throw new PSNotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the provided Runspace from the nested "active" debugger state.
|
||||
@@ -1122,7 +1161,7 @@ namespace System.Management.Automation
|
||||
|
||||
#endregion Call stack management
|
||||
|
||||
#region adding breakpoints
|
||||
#region setting breakpoints
|
||||
|
||||
internal void AddBreakpointCommon(Breakpoint breakpoint)
|
||||
{
|
||||
@@ -1135,30 +1174,14 @@ namespace System.Management.Automation
|
||||
OnBreakpointUpdated(new BreakpointUpdatedEventArgs(breakpoint, BreakpointUpdateType.Set, _idToBreakpoint.Count));
|
||||
}
|
||||
|
||||
private Breakpoint AddCommandBreakpoint(CommandBreakpoint breakpoint)
|
||||
private CommandBreakpoint AddCommandBreakpoint(CommandBreakpoint breakpoint)
|
||||
{
|
||||
AddBreakpointCommon(breakpoint);
|
||||
_commandBreakpoints[breakpoint.Id] = breakpoint;
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
internal Breakpoint NewCommandBreakpoint(string path, string command, ScriptBlock action)
|
||||
{
|
||||
WildcardPattern pattern = WildcardPattern.Get(command, WildcardOptions.Compiled | WildcardOptions.IgnoreCase);
|
||||
|
||||
CheckForBreakpointSupport();
|
||||
return AddCommandBreakpoint(new CommandBreakpoint(path, pattern, command, action));
|
||||
}
|
||||
|
||||
internal Breakpoint NewCommandBreakpoint(string command, ScriptBlock action)
|
||||
{
|
||||
WildcardPattern pattern = WildcardPattern.Get(command, WildcardOptions.Compiled | WildcardOptions.IgnoreCase);
|
||||
|
||||
CheckForBreakpointSupport();
|
||||
return AddCommandBreakpoint(new CommandBreakpoint(null, pattern, command, action));
|
||||
}
|
||||
|
||||
private Breakpoint AddLineBreakpoint(LineBreakpoint breakpoint)
|
||||
private LineBreakpoint AddLineBreakpoint(LineBreakpoint breakpoint)
|
||||
{
|
||||
AddBreakpointCommon(breakpoint);
|
||||
_pendingBreakpoints[breakpoint.Id] = breakpoint;
|
||||
@@ -1188,22 +1211,6 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
internal Breakpoint NewLineBreakpoint(string path, int line, ScriptBlock action)
|
||||
{
|
||||
Diagnostics.Assert(path != null, "caller to verify path is not null");
|
||||
|
||||
CheckForBreakpointSupport();
|
||||
return AddLineBreakpoint(new LineBreakpoint(path, line, action));
|
||||
}
|
||||
|
||||
internal Breakpoint NewStatementBreakpoint(string path, int line, int column, ScriptBlock action)
|
||||
{
|
||||
Diagnostics.Assert(path != null, "caller to verify path is not null");
|
||||
|
||||
CheckForBreakpointSupport();
|
||||
return AddLineBreakpoint(new LineBreakpoint(path, line, column, action));
|
||||
}
|
||||
|
||||
internal VariableBreakpoint AddVariableBreakpoint(VariableBreakpoint breakpoint)
|
||||
{
|
||||
AddBreakpointCommon(breakpoint);
|
||||
@@ -1218,16 +1225,30 @@ namespace System.Management.Automation
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
internal Breakpoint NewVariableBreakpoint(string path, string variableName, VariableAccessMode accessMode, ScriptBlock action)
|
||||
private void UpdateBreakpoints(FunctionContext functionContext)
|
||||
{
|
||||
CheckForBreakpointSupport();
|
||||
return AddVariableBreakpoint(new VariableBreakpoint(path, variableName, accessMode, action));
|
||||
}
|
||||
if (functionContext._breakPoints == null)
|
||||
{
|
||||
// This should be rare - setting a breakpoint inside a script, but debugger hadn't started.
|
||||
SetupBreakpoints(functionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check pending breakpoints to see if any apply to this script.
|
||||
if (string.IsNullOrEmpty(functionContext._file))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
internal Breakpoint NewVariableBreakpoint(string variableName, VariableAccessMode accessMode, ScriptBlock action)
|
||||
{
|
||||
CheckForBreakpointSupport();
|
||||
return AddVariableBreakpoint(new VariableBreakpoint(null, variableName, accessMode, action));
|
||||
foreach ((int breakpointId, LineBreakpoint item) in _pendingBreakpoints)
|
||||
{
|
||||
if (item.IsScriptBreakpoint && item.Script.Equals(functionContext._file, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
SetPendingBreakpoints(functionContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1239,44 +1260,27 @@ namespace System.Management.Automation
|
||||
RaiseBreakpointUpdatedEvent(e);
|
||||
}
|
||||
|
||||
#endregion adding breakpoints
|
||||
#endregion setting breakpoints
|
||||
|
||||
#region removing breakpoints
|
||||
|
||||
// This is the implementation of the Remove-PSBreakpoint cmdlet.
|
||||
internal void RemoveBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
_idToBreakpoint.Remove(breakpoint.Id, out _);
|
||||
|
||||
breakpoint.RemoveSelf(this);
|
||||
|
||||
if (CanDisableDebugger)
|
||||
{
|
||||
SetInternalDebugMode(InternalDebugMode.Disabled);
|
||||
}
|
||||
|
||||
OnBreakpointUpdated(new BreakpointUpdatedEventArgs(breakpoint, BreakpointUpdateType.Removed, _idToBreakpoint.Count));
|
||||
}
|
||||
|
||||
internal void RemoveVariableBreakpoint(VariableBreakpoint breakpoint)
|
||||
{
|
||||
internal bool RemoveVariableBreakpoint(VariableBreakpoint breakpoint) =>
|
||||
_variableBreakpoints[breakpoint.Variable].Remove(breakpoint.Id, out _);
|
||||
}
|
||||
|
||||
internal void RemoveCommandBreakpoint(CommandBreakpoint breakpoint)
|
||||
{
|
||||
internal bool RemoveCommandBreakpoint(CommandBreakpoint breakpoint) =>
|
||||
_commandBreakpoints.Remove(breakpoint.Id, out _);
|
||||
}
|
||||
|
||||
internal void RemoveLineBreakpoint(LineBreakpoint breakpoint)
|
||||
internal bool RemoveLineBreakpoint(LineBreakpoint breakpoint)
|
||||
{
|
||||
_pendingBreakpoints.Remove(breakpoint.Id, out _);
|
||||
bool removed = _pendingBreakpoints.Remove(breakpoint.Id, out _);
|
||||
|
||||
Tuple<WeakReference, ConcurrentDictionary<int, LineBreakpoint>> value;
|
||||
if (_boundBreakpoints.TryGetValue(breakpoint.Script, out value))
|
||||
{
|
||||
value.Item2.Remove(breakpoint.Id, out _);
|
||||
removed = value.Item2.Remove(breakpoint.Id, out _);
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
#endregion removing breakpoints
|
||||
@@ -1386,24 +1390,6 @@ namespace System.Management.Automation
|
||||
OnDebuggerStop(invocationInfo, breakpoints.ToList<Breakpoint>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a breakpoint by id, primarily for Enable/Disable/Remove-PSBreakpoint cmdlets.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the breakpoint you want.</param>
|
||||
public override Breakpoint GetBreakpoint(int id)
|
||||
{
|
||||
_idToBreakpoint.TryGetValue(id, out Breakpoint breakpoint);
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns breakpoints primarily for the Get-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
public override List<Breakpoint> GetBreakpoints()
|
||||
{
|
||||
return (from bp in _idToBreakpoint.Values orderby bp.Id select bp).ToList();
|
||||
}
|
||||
|
||||
// Return the line breakpoints bound in a specific script block (used when a sequence point
|
||||
// is hit, to find which breakpoints are set on that sequence point.)
|
||||
internal List<LineBreakpoint> GetBoundBreakpoints(IScriptExtent[] sequencePoints)
|
||||
@@ -1458,30 +1444,6 @@ namespace System.Management.Automation
|
||||
return breaks;
|
||||
}
|
||||
|
||||
#endregion triggering breakpoints
|
||||
|
||||
#region enabling/disabling breakpoints
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of Enable-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
internal void EnableBreakpoint(Breakpoint bp)
|
||||
{
|
||||
bp.SetEnabled(true);
|
||||
OnBreakpointUpdated(new BreakpointUpdatedEventArgs(bp, BreakpointUpdateType.Enabled, _idToBreakpoint.Count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of Disable-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
internal void DisableBreakpoint(Breakpoint bp)
|
||||
{
|
||||
bp.SetEnabled(false);
|
||||
OnBreakpointUpdated(new BreakpointUpdatedEventArgs(bp, BreakpointUpdateType.Disabled, _idToBreakpoint.Count));
|
||||
}
|
||||
|
||||
#endregion enabling/disabling breakpoints
|
||||
|
||||
internal void OnSequencePointHit(FunctionContext functionContext)
|
||||
{
|
||||
if (_context.ShouldTraceStatement && !_callStack.Last().IsFrameHidden && !functionContext._debuggerStepThrough)
|
||||
@@ -1533,34 +1495,7 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBreakpoints(FunctionContext functionContext)
|
||||
{
|
||||
if (functionContext._breakPoints == null)
|
||||
{
|
||||
// This should be rare - setting a breakpoint inside a script, but debugger hadn't started.
|
||||
SetupBreakpoints(functionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check pending breakpoints to see if any apply to this script.
|
||||
if (string.IsNullOrEmpty(functionContext._file)) { return; }
|
||||
|
||||
bool havePendingBreakpoint = false;
|
||||
foreach ((int breakpointId, LineBreakpoint item) in _pendingBreakpoints)
|
||||
{
|
||||
if (item.IsScriptBreakpoint && item.Script.Equals(functionContext._file, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
havePendingBreakpoint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (havePendingBreakpoint)
|
||||
{
|
||||
SetPendingBreakpoints(functionContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion triggering breakpoints
|
||||
|
||||
#endregion internal methods
|
||||
|
||||
@@ -2448,39 +2383,6 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SetBreakpoints.
|
||||
/// </summary>
|
||||
/// <param name="breakpoints"></param>
|
||||
public override void SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
|
||||
{
|
||||
if (breakpoints == null)
|
||||
{
|
||||
throw new PSArgumentNullException("breakpoints");
|
||||
}
|
||||
|
||||
foreach (var breakpoint in breakpoints)
|
||||
{
|
||||
if (_idToBreakpoint.ContainsKey(breakpoint.Id)) { continue; }
|
||||
|
||||
switch (breakpoint)
|
||||
{
|
||||
case LineBreakpoint lineBp:
|
||||
AddLineBreakpoint(lineBp);
|
||||
continue;
|
||||
case CommandBreakpoint cmdBp:
|
||||
AddCommandBreakpoint(cmdBp);
|
||||
continue;
|
||||
case VariableBreakpoint variableBp:
|
||||
AddVariableBreakpoint(variableBp);
|
||||
continue;
|
||||
default:
|
||||
// Unreachable default block
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True when debugger is active with breakpoints.
|
||||
/// </summary>
|
||||
@@ -2676,16 +2578,147 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
#region Breakpoints
|
||||
|
||||
/// <summary>
|
||||
/// Get a breakpoint by id, primarily for Enable/Disable/Remove-PSBreakpoint cmdlets.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the breakpoint you want.</param>
|
||||
public override Breakpoint GetBreakpoint(int id)
|
||||
{
|
||||
_idToBreakpoint.TryGetValue(id, out Breakpoint breakpoint);
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns breakpoints primarily for the Get-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
public override List<Breakpoint> GetBreakpoints()
|
||||
{
|
||||
return (from bp in _idToBreakpoint.Values orderby bp.Id select bp).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a command breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="command">The name of the command that will trigger the breakpoint. This value is required and may not be null.</param>
|
||||
/// <param name="action">The action to take when the breakpoint is hit. If null, PowerShell will break into the debugger when the breakpoint is hit.</param>
|
||||
/// <param name="path">The path to the script file where the breakpoint may be hit. If null, the breakpoint may be hit anywhere the command is invoked.</param>
|
||||
/// <returns></returns>
|
||||
public override CommandBreakpoint SetCommandBreakpoint(string command, ScriptBlock action = null, string path = null)
|
||||
{
|
||||
Diagnostics.Assert(!string.IsNullOrEmpty(command), "Caller to verify command is not null or empty.");
|
||||
|
||||
WildcardPattern pattern = WildcardPattern.Get(command, WildcardOptions.Compiled | WildcardOptions.IgnoreCase);
|
||||
|
||||
CheckForBreakpointSupport();
|
||||
return AddCommandBreakpoint(new CommandBreakpoint(path, pattern, command, action));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a line breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the script file where the breakpoint may be hit. This value is required and may not be null.</param>
|
||||
/// <param name="line">The line in the script file where the breakpoint may be hit. This value is required and must be greater than or equal to 1.</param>
|
||||
/// <param name="column">The column in the script file where the breakpoint may be hit. If 0, the breakpoint will trigger on any statement on the line.</param>
|
||||
/// <param name="action">The action to take when the breakpoint is hit. If null, PowerShell will break into the debugger when the breakpoint is hit.</param>
|
||||
/// <returns></returns>
|
||||
public override LineBreakpoint SetLineBreakpoint(string path, int line, int column = 0, ScriptBlock action = null)
|
||||
{
|
||||
Diagnostics.Assert(path != null, "Caller to verify path is not null.");
|
||||
Diagnostics.Assert(line > 0, "Caller to verify line is greater than 0.");
|
||||
|
||||
CheckForBreakpointSupport();
|
||||
return AddLineBreakpoint(new LineBreakpoint(path, line, column, action));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a variable breakpoint in the debugger.
|
||||
/// </summary>
|
||||
/// <param name="variableName">The name of the variable that will trigger the breakpoint. This value is required and may not be null.</param>
|
||||
/// <param name="accessMode">The variable access mode that will trigger the breakpoint. By default variable breakpoints will trigger only when the variable is updated.</param>
|
||||
/// <param name="action">The action to take when the breakpoint is hit. If null, PowerShell will break into the debugger when the breakpoint is hit.</param>
|
||||
/// <param name="path">The path to the script file where the breakpoint may be hit. If null, the breakpoint may be hit anywhere the variable is accessed using the specified access mode.</param>
|
||||
/// <returns></returns>
|
||||
public override VariableBreakpoint SetVariableBreakpoint(string variableName, VariableAccessMode accessMode = VariableAccessMode.Write, ScriptBlock action = null, string path = null)
|
||||
{
|
||||
Diagnostics.Assert(!string.IsNullOrEmpty(variableName), "Caller to verify variableName is not null or empty.");
|
||||
|
||||
CheckForBreakpointSupport();
|
||||
return AddVariableBreakpoint(new VariableBreakpoint(path, variableName, accessMode, action));
|
||||
}
|
||||
|
||||
// This is the implementation of the Remove-PSBreakpoint cmdlet.
|
||||
public override bool RemoveBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
Diagnostics.Assert(breakpoint != null, "Caller to verify the breakpoint is not null.");
|
||||
|
||||
if (_idToBreakpoint.Remove(breakpoint.Id, out _))
|
||||
{
|
||||
breakpoint.RemoveSelf(this);
|
||||
|
||||
if (CanDisableDebugger)
|
||||
{
|
||||
SetInternalDebugMode(InternalDebugMode.Disabled);
|
||||
}
|
||||
|
||||
OnBreakpointUpdated(new BreakpointUpdatedEventArgs(breakpoint, BreakpointUpdateType.Removed, _idToBreakpoint.Count));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// This is the implementation of the Enable-PSBreakpoint cmdlet.
|
||||
public override Breakpoint EnableBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
Diagnostics.Assert(breakpoint != null, "Caller to verify the breakpoint is not null.");
|
||||
|
||||
if (_idToBreakpoint.TryGetValue(breakpoint.Id, out _))
|
||||
{
|
||||
breakpoint.SetEnabled(true);
|
||||
OnBreakpointUpdated(new BreakpointUpdatedEventArgs(breakpoint, BreakpointUpdateType.Enabled, _idToBreakpoint.Count));
|
||||
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// This is the implementation of the Disable-PSBreakpoint cmdlet.
|
||||
public override Breakpoint DisableBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
Diagnostics.Assert(breakpoint != null, "Caller to verify the breakpoint is not null.");
|
||||
|
||||
if (_idToBreakpoint.TryGetValue(breakpoint.Id, out _))
|
||||
{
|
||||
breakpoint.SetEnabled(false);
|
||||
OnBreakpointUpdated(new BreakpointUpdatedEventArgs(breakpoint, BreakpointUpdateType.Disabled, _idToBreakpoint.Count));
|
||||
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion Breakpoints
|
||||
|
||||
#region Job Debugging
|
||||
|
||||
/// <summary>
|
||||
/// Sets up debugger to debug provided job or its child jobs.
|
||||
/// </summary>
|
||||
/// <param name="job">
|
||||
/// Job object that is either a debuggable job or a container
|
||||
/// of debuggable child jobs.
|
||||
/// Job object that is either a debuggable job or a container of
|
||||
/// debuggable child jobs.
|
||||
/// </param>
|
||||
internal override void DebugJob(Job job)
|
||||
/// <param name="breakAll">
|
||||
/// If true, the debugger automatically invokes a break all when it
|
||||
/// attaches to the job.
|
||||
/// </param>
|
||||
internal override void DebugJob(Job job, bool breakAll)
|
||||
{
|
||||
if (job == null) { throw new PSArgumentNullException("job"); }
|
||||
|
||||
@@ -2699,13 +2732,13 @@ namespace System.Management.Automation
|
||||
|
||||
// If a debuggable job was passed in then add it to the
|
||||
// job running list.
|
||||
bool jobsAdded = TryAddDebugJob(job);
|
||||
bool jobsAdded = TryAddDebugJob(job, breakAll);
|
||||
if (!jobsAdded)
|
||||
{
|
||||
// Otherwise treat as parent Job and iterate over child jobs.
|
||||
foreach (Job childJob in job.ChildJobs)
|
||||
{
|
||||
if (TryAddDebugJob(childJob) && !jobsAdded)
|
||||
if (TryAddDebugJob(childJob, breakAll) && !jobsAdded)
|
||||
{
|
||||
jobsAdded = true;
|
||||
}
|
||||
@@ -2718,7 +2751,7 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryAddDebugJob(Job job)
|
||||
private bool TryAddDebugJob(Job job, bool breakAll)
|
||||
{
|
||||
IJobDebugger debuggableJob = job as IJobDebugger;
|
||||
if ((debuggableJob != null) && (debuggableJob.Debugger != null) &&
|
||||
@@ -2731,7 +2764,7 @@ namespace System.Management.Automation
|
||||
SetDebugJobAsync(debuggableJob, false);
|
||||
AddToJobRunningList(
|
||||
new PSJobStartEventArgs(job, debuggableJob.Debugger, false),
|
||||
DebuggerResumeAction.StepInto);
|
||||
breakAll ? DebuggerResumeAction.StepInto : DebuggerResumeAction.Continue);
|
||||
|
||||
// Raise debug stop event if job is already in stopped state.
|
||||
if (jobDebugAlreadyStopped)
|
||||
@@ -2794,17 +2827,17 @@ namespace System.Management.Automation
|
||||
|
||||
#region Runspace Debugging
|
||||
|
||||
internal override void DebugRunspace(Runspace runspace)
|
||||
{
|
||||
DebugRunspace(runspace, disableBreakAll: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up debugger to debug provided Runspace in a nested debug session.
|
||||
/// </summary>
|
||||
/// <param name="runspace">Runspace to debug.</param>
|
||||
/// <param name="disableBreakAll">When specified, it will not turn on BreakAll.</param>
|
||||
internal override void DebugRunspace(Runspace runspace, bool disableBreakAll)
|
||||
/// <param name="runspace">
|
||||
/// Runspace to debug.
|
||||
/// </param>
|
||||
/// <param name="breakAll">
|
||||
/// When true, this command will invoke a BreakAll when the debugger is
|
||||
/// first attached.
|
||||
/// </param>
|
||||
internal override void DebugRunspace(Runspace runspace, bool breakAll)
|
||||
{
|
||||
if (runspace == null)
|
||||
{
|
||||
@@ -2839,7 +2872,7 @@ namespace System.Management.Automation
|
||||
|
||||
AddToRunningRunspaceList(new PSStandaloneMonitorRunspaceInfo(runspace));
|
||||
|
||||
if (!runspace.Debugger.InBreakpoint && !disableBreakAll)
|
||||
if (!runspace.Debugger.InBreakpoint && breakAll)
|
||||
{
|
||||
EnableDebuggerStepping(EnableNestedType.NestedRunspace);
|
||||
}
|
||||
@@ -3745,7 +3778,7 @@ namespace System.Management.Automation
|
||||
{
|
||||
WaitForReadyDebug();
|
||||
|
||||
DebugRunspace(runspace);
|
||||
DebugRunspace(runspace, breakAll:true);
|
||||
|
||||
// Block this event thread until debugging has ended.
|
||||
WaitForDebugComplete();
|
||||
@@ -4077,28 +4110,30 @@ namespace System.Management.Automation
|
||||
return _wrappedDebugger.ProcessCommand(command, output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the provided set of breakpoints to the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoints">Breakpoints.</param>
|
||||
public override void SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
|
||||
{
|
||||
_wrappedDebugger.SetBreakpoints(breakpoints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a breakpoint by id, primarily for Enable/Disable/Remove-PSBreakpoint cmdlets.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the breakpoint you want.</param>
|
||||
public override Breakpoint GetBreakpoint(int id) =>
|
||||
_wrappedDebugger.GetBreakpoint(id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns breakpoints primarily for the Get-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
public override List<Breakpoint> GetBreakpoints() =>
|
||||
_wrappedDebugger.GetBreakpoints();
|
||||
|
||||
public override CommandBreakpoint SetCommandBreakpoint(string command, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.SetCommandBreakpoint(command, action, path);
|
||||
|
||||
public override LineBreakpoint SetLineBreakpoint(string path, int line, int column = 0, ScriptBlock action = null) =>
|
||||
_wrappedDebugger.SetLineBreakpoint(path, line, column, action);
|
||||
|
||||
public override VariableBreakpoint SetVariableBreakpoint(string variableName, VariableAccessMode accessMode = VariableAccessMode.Write, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.SetVariableBreakpoint(variableName, accessMode, action, path);
|
||||
|
||||
public override bool RemoveBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.RemoveBreakpoint(breakpoint);
|
||||
|
||||
public override Breakpoint EnableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.EnableBreakpoint(breakpoint);
|
||||
|
||||
public override Breakpoint DisableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.DisableBreakpoint(breakpoint);
|
||||
|
||||
/// <summary>
|
||||
/// SetDebuggerAction.
|
||||
/// </summary>
|
||||
@@ -5397,12 +5432,6 @@ namespace System.Management.Automation.Internal
|
||||
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes", Justification = "Needed Internal use only")]
|
||||
public static class DebuggerUtils
|
||||
{
|
||||
internal const string SetDebugModeFunctionName = "__Set-PSDebugMode";
|
||||
internal const string SetDebuggerActionFunctionName = "__Set-PSDebuggerAction";
|
||||
internal const string GetDebuggerStopArgsFunctionName = "__Get-PSDebuggerStopArgs";
|
||||
internal const string SetDebuggerStepMode = "__Set-PSDebuggerStepMode";
|
||||
internal const string SetPSUnhandledBreakpointMode = "__Set-PSUnhandledBreakpointMode";
|
||||
|
||||
private static SortedSet<string> s_noHistoryCommandNames = new SortedSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"prompt",
|
||||
|
||||
@@ -1060,15 +1060,6 @@ namespace System.Management.Automation.PSTasks
|
||||
return _wrappedDebugger.ProcessCommand(command, output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the provided set of breakpoints to the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoints">List of breakpoints.</param>
|
||||
public override void SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
|
||||
{
|
||||
_wrappedDebugger.SetBreakpoints(breakpoints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the debugger resume action.
|
||||
/// </summary>
|
||||
@@ -1078,6 +1069,27 @@ namespace System.Management.Automation.PSTasks
|
||||
_wrappedDebugger.SetDebuggerAction(resumeAction);
|
||||
}
|
||||
|
||||
public override Breakpoint GetBreakpoint(int id) =>
|
||||
_wrappedDebugger.GetBreakpoint(id);
|
||||
|
||||
public override CommandBreakpoint SetCommandBreakpoint(string command, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.SetCommandBreakpoint(command, action, path);
|
||||
|
||||
public override VariableBreakpoint SetVariableBreakpoint(string variableName, VariableAccessMode accessMode = VariableAccessMode.Write, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.SetVariableBreakpoint(variableName, accessMode, action, path);
|
||||
|
||||
public override LineBreakpoint SetLineBreakpoint(string path, int line, int column = 0, ScriptBlock action = null) =>
|
||||
_wrappedDebugger.SetLineBreakpoint(path, line, column, action);
|
||||
|
||||
public override Breakpoint EnableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.EnableBreakpoint(breakpoint);
|
||||
|
||||
public override Breakpoint DisableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.DisableBreakpoint(breakpoint);
|
||||
|
||||
public override bool RemoveBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.RemoveBreakpoint(breakpoint);
|
||||
|
||||
/// <summary>
|
||||
/// Stops a running command.
|
||||
/// </summary>
|
||||
|
||||
@@ -3909,28 +3909,30 @@ namespace System.Management.Automation
|
||||
return _wrappedDebugger.ProcessCommand(command, output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the provided set of breakpoints to the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoints">Breakpoints.</param>
|
||||
public override void SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
|
||||
{
|
||||
_wrappedDebugger.SetBreakpoints(breakpoints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a breakpoint by id, primarily for Enable/Disable/Remove-PSBreakpoint cmdlets.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the breakpoint you want.</param>
|
||||
public override Breakpoint GetBreakpoint(int id) =>
|
||||
_wrappedDebugger.GetBreakpoint(id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns breakpoints primarily for the Get-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
public override List<Breakpoint> GetBreakpoints() =>
|
||||
_wrappedDebugger.GetBreakpoints();
|
||||
|
||||
public override CommandBreakpoint SetCommandBreakpoint(string command, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.SetCommandBreakpoint(command, action, path);
|
||||
|
||||
public override LineBreakpoint SetLineBreakpoint(string path, int line, int column = 0, ScriptBlock action = null) =>
|
||||
_wrappedDebugger.SetLineBreakpoint(path, line, column, action);
|
||||
|
||||
public override VariableBreakpoint SetVariableBreakpoint(string variableName, VariableAccessMode accessMode = VariableAccessMode.Write, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.SetVariableBreakpoint(variableName, accessMode, action, path);
|
||||
|
||||
public override bool RemoveBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.RemoveBreakpoint(breakpoint);
|
||||
|
||||
public override Breakpoint EnableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.EnableBreakpoint(breakpoint);
|
||||
|
||||
public override Breakpoint DisableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.DisableBreakpoint(breakpoint);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the debugger resume action.
|
||||
/// </summary>
|
||||
|
||||
@@ -1809,7 +1809,8 @@ namespace System.Management.Automation
|
||||
private bool _remoteDebugSupported;
|
||||
private bool _isActive;
|
||||
private int _breakpointCount;
|
||||
private Version _serverPSVersion;
|
||||
private RemoteDebuggingCapability _remoteDebuggingCapability;
|
||||
private bool? _remoteBreakpointManagementIsSupported;
|
||||
private volatile bool _handleDebuggerStop;
|
||||
private bool _isDebuggerSteppingEnabled;
|
||||
private UnhandledBreakpointProcessingMode _unhandledBreakpointMode;
|
||||
@@ -2005,27 +2006,165 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the provided set of breakpoints to the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoints">Breakpoints.</param>
|
||||
public override void SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
|
||||
{
|
||||
_runspace.Debugger?.SetBreakpoints(breakpoints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a breakpoint by id, primarily for Enable/Disable/Remove-PSBreakpoint cmdlets.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the breakpoint you want.</param>
|
||||
public override Breakpoint GetBreakpoint(int id) =>
|
||||
_runspace.Debugger?.GetBreakpoint(id);
|
||||
public override Breakpoint GetBreakpoint(int id)
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.GetBreakpoint);
|
||||
|
||||
return InvokeRemoteBreakpointFunction<Breakpoint>(
|
||||
RemoteDebuggingCommands.GetBreakpoint,
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "Id", id },
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns breakpoints primarily for the Get-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
public override List<Breakpoint> GetBreakpoints() =>
|
||||
_runspace.Debugger?.GetBreakpoints();
|
||||
public override List<Breakpoint> GetBreakpoints()
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.GetBreakpoint);
|
||||
|
||||
CheckForValidateState();
|
||||
|
||||
var breakpoints = new List<Breakpoint>();
|
||||
|
||||
using (PowerShell ps = GetNestedPowerShell())
|
||||
{
|
||||
ps.AddCommand(RemoteDebuggingCommands.GetBreakpoint);
|
||||
|
||||
Collection<PSObject> output = ps.Invoke<PSObject>();
|
||||
foreach (var item in output)
|
||||
{
|
||||
if (item?.BaseObject is Breakpoint bp)
|
||||
{
|
||||
breakpoints.Add(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return breakpoints;
|
||||
}
|
||||
|
||||
public override CommandBreakpoint SetCommandBreakpoint(string command, ScriptBlock action = null, string path = null)
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.SetBreakpoint);
|
||||
|
||||
var functionParameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "Command", command },
|
||||
};
|
||||
|
||||
if (action != null)
|
||||
{
|
||||
functionParameters.Add("Action", action);
|
||||
}
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
functionParameters.Add("Script", path);
|
||||
}
|
||||
|
||||
return InvokeRemoteBreakpointFunction<CommandBreakpoint>(RemoteDebuggingCommands.SetBreakpoint, functionParameters);
|
||||
}
|
||||
|
||||
public override LineBreakpoint SetLineBreakpoint(string path, int line, int column = 0, ScriptBlock action = null)
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.SetBreakpoint);
|
||||
|
||||
var functionParameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "Script", path },
|
||||
{ "Line", line },
|
||||
};
|
||||
|
||||
if (column != 0)
|
||||
{
|
||||
functionParameters.Add("Column", column);
|
||||
}
|
||||
|
||||
if (action != null)
|
||||
{
|
||||
functionParameters.Add("Action", action);
|
||||
}
|
||||
|
||||
return InvokeRemoteBreakpointFunction<LineBreakpoint>(RemoteDebuggingCommands.SetBreakpoint, functionParameters);
|
||||
}
|
||||
|
||||
public override VariableBreakpoint SetVariableBreakpoint(string variableName, VariableAccessMode accessMode = VariableAccessMode.Write, ScriptBlock action = null, string path = null)
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.SetBreakpoint);
|
||||
|
||||
var functionParameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "Variable", variableName },
|
||||
};
|
||||
|
||||
if (accessMode != VariableAccessMode.Write)
|
||||
{
|
||||
functionParameters.Add("Mode", accessMode);
|
||||
}
|
||||
|
||||
if (action != null)
|
||||
{
|
||||
functionParameters.Add("Action", action);
|
||||
}
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
functionParameters.Add("Script", path);
|
||||
}
|
||||
|
||||
return InvokeRemoteBreakpointFunction<VariableBreakpoint>(RemoteDebuggingCommands.SetBreakpoint, functionParameters);
|
||||
}
|
||||
|
||||
public override bool RemoveBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.RemoveBreakpoint);
|
||||
|
||||
return InvokeRemoteBreakpointFunction<bool>(
|
||||
RemoteDebuggingCommands.RemoveBreakpoint,
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "Id", breakpoint.Id },
|
||||
});
|
||||
}
|
||||
|
||||
public override Breakpoint EnableBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.EnableBreakpoint);
|
||||
|
||||
return InvokeRemoteBreakpointFunction<Breakpoint>(
|
||||
RemoteDebuggingCommands.EnableBreakpoint,
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "Id", breakpoint.Id },
|
||||
});
|
||||
}
|
||||
|
||||
public override Breakpoint DisableBreakpoint(Breakpoint breakpoint)
|
||||
{
|
||||
// This is supported only for PowerShell versions >= 7.0
|
||||
CheckRemoteBreakpointManagementSupport(RemoteDebuggingCommands.DisableBreakpoint);
|
||||
|
||||
return InvokeRemoteBreakpointFunction<Breakpoint>(
|
||||
RemoteDebuggingCommands.DisableBreakpoint,
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "Id", breakpoint.Id },
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SetDebuggerAction.
|
||||
@@ -2039,7 +2178,7 @@ namespace System.Management.Automation
|
||||
|
||||
using (PowerShell ps = GetNestedPowerShell())
|
||||
{
|
||||
ps.AddCommand(DebuggerUtils.SetDebuggerActionFunctionName).AddParameter("ResumeAction", resumeAction);
|
||||
ps.AddCommand(RemoteDebuggingCommands.SetDebuggerAction).AddParameter("ResumeAction", resumeAction);
|
||||
ps.Invoke();
|
||||
|
||||
// If an error exception is returned then throw it here.
|
||||
@@ -2065,7 +2204,7 @@ namespace System.Management.Automation
|
||||
{
|
||||
using (PowerShell ps = GetNestedPowerShell())
|
||||
{
|
||||
ps.AddCommand(DebuggerUtils.GetDebuggerStopArgsFunctionName);
|
||||
ps.AddCommand(RemoteDebuggingCommands.GetDebuggerStopArgs);
|
||||
Collection<PSObject> output = ps.Invoke<PSObject>();
|
||||
foreach (var item in output)
|
||||
{
|
||||
@@ -2102,7 +2241,7 @@ namespace System.Management.Automation
|
||||
using (PowerShell ps = GetNestedPowerShell())
|
||||
{
|
||||
ps.SetIsNested(false);
|
||||
ps.AddCommand(DebuggerUtils.SetDebugModeFunctionName).AddParameter("Mode", mode);
|
||||
ps.AddCommand(RemoteDebuggingCommands.SetDebugMode).AddParameter("Mode", mode);
|
||||
ps.Invoke();
|
||||
}
|
||||
|
||||
@@ -2120,8 +2259,7 @@ namespace System.Management.Automation
|
||||
CheckForValidateState();
|
||||
|
||||
// This is supported only for PowerShell versions >= 5.0
|
||||
if ((_serverPSVersion == null) ||
|
||||
(_serverPSVersion.Major < PSVersionInfo.PSV5Version.Major))
|
||||
if (!_remoteDebuggingCapability.IsCommandSupported(RemoteDebuggingCommands.SetDebuggerStepMode))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -2134,7 +2272,7 @@ namespace System.Management.Automation
|
||||
// Send Enable-DebuggerStepping virtual command.
|
||||
using (PowerShell ps = GetNestedPowerShell())
|
||||
{
|
||||
ps.AddCommand(DebuggerUtils.SetDebuggerStepMode).AddParameter("Enabled", enabled);
|
||||
ps.AddCommand(RemoteDebuggingCommands.SetDebuggerStepMode).AddParameter("Enabled", enabled);
|
||||
ps.Invoke();
|
||||
_isDebuggerSteppingEnabled = enabled;
|
||||
}
|
||||
@@ -2202,8 +2340,7 @@ namespace System.Management.Automation
|
||||
CheckForValidateState();
|
||||
|
||||
// This is supported only for PowerShell versions >= 5.0
|
||||
if ((_serverPSVersion == null) ||
|
||||
(_serverPSVersion < PSVersionInfo.PSV5Version))
|
||||
if (!_remoteDebuggingCapability.IsCommandSupported(RemoteDebuggingCommands.SetUnhandledBreakpointMode))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -2213,7 +2350,7 @@ namespace System.Management.Automation
|
||||
// Send Set-PSUnhandledBreakpointMode virtual command.
|
||||
using (PowerShell ps = GetNestedPowerShell())
|
||||
{
|
||||
ps.AddCommand(DebuggerUtils.SetPSUnhandledBreakpointMode).AddParameter("UnhandledBreakpointMode", value);
|
||||
ps.AddCommand(RemoteDebuggingCommands.SetUnhandledBreakpointMode).AddParameter("UnhandledBreakpointMode", value);
|
||||
ps.Invoke();
|
||||
}
|
||||
|
||||
@@ -2303,7 +2440,7 @@ namespace System.Management.Automation
|
||||
SetRemoteDebug(true, RunspaceAvailability.RemoteDebug);
|
||||
}
|
||||
|
||||
_serverPSVersion = serverPSVersion;
|
||||
_remoteDebuggingCapability = RemoteDebuggingCapability.CreateDebuggingCapability(serverPSVersion);
|
||||
|
||||
_breakpointCount = breakpointCount;
|
||||
_isDebuggerSteppingEnabled = breakAll;
|
||||
@@ -2610,6 +2747,59 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
private T InvokeRemoteBreakpointFunction<T>(string functionName, Dictionary<string, object> parameters)
|
||||
{
|
||||
CheckForValidateState();
|
||||
|
||||
using (PowerShell ps = GetNestedPowerShell())
|
||||
{
|
||||
ps.AddCommand(functionName);
|
||||
foreach (var parameterName in parameters.Keys)
|
||||
{
|
||||
ps.AddParameter(parameterName, parameters[parameterName]);
|
||||
}
|
||||
|
||||
Collection<PSObject> output = ps.Invoke<PSObject>();
|
||||
|
||||
// If an error exception is returned then throw it here.
|
||||
if (ps.ErrorBuffer.Count > 0)
|
||||
{
|
||||
Exception e = ps.ErrorBuffer[0].Exception;
|
||||
if (e != null)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// This helper is only used to return a single output item of type T.
|
||||
foreach (var item in output)
|
||||
{
|
||||
if (item?.BaseObject is T)
|
||||
{
|
||||
return (T)item.BaseObject;
|
||||
}
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckRemoteBreakpointManagementSupport(string breakpointCommandNameToCheck)
|
||||
{
|
||||
if (_remoteBreakpointManagementIsSupported == null)
|
||||
{
|
||||
_remoteBreakpointManagementIsSupported = _remoteDebuggingCapability.IsCommandSupported(breakpointCommandNameToCheck);
|
||||
}
|
||||
|
||||
if (!_remoteBreakpointManagementIsSupported.Value)
|
||||
{
|
||||
throw new PSNotSupportedException(
|
||||
StringUtil.Format(
|
||||
DebuggerStrings.CommandNotSupportedForRemoteUseInServerDebugger,
|
||||
RemoteDebuggingCommands.CleanCommandName(breakpointCommandNameToCheck)));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,13 @@ namespace Microsoft.PowerShell.Commands
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a flag that tells PowerShell to automatically perform a BreakAll when the debugger is attached to the remote target.
|
||||
/// </summary>
|
||||
[Experimental("Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace", ExperimentAction.Show)]
|
||||
[Parameter]
|
||||
public SwitchParameter BreakAll { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
@@ -177,7 +184,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
// Set up host script debugger to debug the job.
|
||||
_debugger = runspace.Debugger;
|
||||
_debugger.DebugJob(_job);
|
||||
_debugger.DebugJob(_job, breakAll: BreakAll);
|
||||
|
||||
// Blocking call. Send job output to host UI while debugging and wait for Job completion.
|
||||
WaitAndReceiveJobOutput();
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Management.Automation.Remoting
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains information about the debugging capability of the server side of the
|
||||
/// MS-PSRDP connection. The functionality that is supported is determined by the PowerShell
|
||||
/// version on the server. These capabilities will be used in remote debugging sessions to
|
||||
/// determine what is supported by the server.
|
||||
/// </summary>
|
||||
internal class RemoteDebuggingCapability
|
||||
{
|
||||
private readonly HashSet<string> _supportedCommands = new HashSet<string>();
|
||||
|
||||
internal Version PSVersion { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RemoteDebuggingCapability"/> class.
|
||||
/// </summary>
|
||||
/// <param name="powerShellVersion">
|
||||
/// The version of PowerShell used on the remote server debugger.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This should only be invoked by the static create method.
|
||||
/// </remarks>
|
||||
private RemoteDebuggingCapability(Version powerShellVersion)
|
||||
{
|
||||
PSVersion = powerShellVersion;
|
||||
|
||||
// Commands available in all server versions
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.GetDebuggerStopArgs);
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.SetDebuggerAction);
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.SetDebugMode);
|
||||
|
||||
if (PSVersion == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Commands added in v5
|
||||
if (PSVersion.Major >= PSVersionInfo.PSV5Version.Major)
|
||||
{
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.SetDebuggerStepMode);
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.SetUnhandledBreakpointMode);
|
||||
}
|
||||
|
||||
// Commands added in v7
|
||||
if (PSVersion.Major >= PSVersionInfo.PSV7Version.Major)
|
||||
{
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.GetBreakpoint);
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.SetBreakpoint);
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.EnableBreakpoint);
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.DisableBreakpoint);
|
||||
_supportedCommands.Add(RemoteDebuggingCommands.RemoveBreakpoint);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="RemoteDebuggingCapability"/> instance that can be
|
||||
/// used to identify the remoting capabilities of the server debugger.
|
||||
/// </summary>
|
||||
/// <param name="powerShellVersion">
|
||||
/// The version of PowerShell used on the remote server debugger.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new RemoteDebuggingCapability instance that is based on the version
|
||||
/// of PowerShell used on the remote server debugger.
|
||||
/// </returns>
|
||||
internal static RemoteDebuggingCapability CreateDebuggingCapability(Version powerShellVersion) =>
|
||||
new RemoteDebuggingCapability(powerShellVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a command is supported in the server version used to create
|
||||
/// this instance.
|
||||
/// </summary>
|
||||
/// <param name="commandName">
|
||||
/// The name of the command to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// True if the command is supported; false otherwise.
|
||||
/// </returns>
|
||||
internal bool IsCommandSupported(string commandName) =>
|
||||
_supportedCommands.Contains(commandName);
|
||||
}
|
||||
|
||||
internal static class RemoteDebuggingCommands
|
||||
{
|
||||
#region DO NOT REMOVE OR CHANGE THE VALUES OF THESE CONSTANTS - it will break remote debugging compatibility with PowerShell
|
||||
|
||||
// Commands related to debugger stop events
|
||||
internal const string GetDebuggerStopArgs = "__Get-PSDebuggerStopArgs";
|
||||
internal const string SetDebuggerAction = "__Set-PSDebuggerAction";
|
||||
|
||||
// Miscellaneous debug commands
|
||||
internal const string SetDebuggerStepMode = "__Set-PSDebuggerStepMode";
|
||||
internal const string SetDebugMode = "__Set-PSDebugMode";
|
||||
internal const string SetUnhandledBreakpointMode = "__Set-PSUnhandledBreakpointMode";
|
||||
|
||||
// Breakpoint commands
|
||||
internal const string GetBreakpoint = "__Get-PSBreakpoint";
|
||||
internal const string SetBreakpoint = "__Set-PSBreakpoint";
|
||||
internal const string EnableBreakpoint = "__Enable-PSBreakpoint";
|
||||
internal const string DisableBreakpoint = "__Disable-PSBreakpoint";
|
||||
internal const string RemoveBreakpoint = "__Remove-PSBreakpoint";
|
||||
|
||||
#endregion
|
||||
|
||||
internal static string CleanCommandName(string commandName)
|
||||
{
|
||||
return commandName.TrimStart('_');
|
||||
}
|
||||
}
|
||||
}
|
||||
+210
-87
@@ -704,9 +704,9 @@ namespace System.Management.Automation
|
||||
/// <summary>
|
||||
/// Handle the invocation of powershell.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of this event, unused.</param>
|
||||
/// <param name="_">Sender of this event, unused.</param>
|
||||
/// <param name="eventArgs">Arguments describing this event.</param>
|
||||
private void HandleCreateAndInvokePowerShell(object sender, RemoteDataEventArgs<RemoteDataObject<PSObject>> eventArgs)
|
||||
private void HandleCreateAndInvokePowerShell(object _, RemoteDataEventArgs<RemoteDataObject<PSObject>> eventArgs)
|
||||
{
|
||||
RemoteDataObject<PSObject> data = eventArgs.Data;
|
||||
|
||||
@@ -1194,7 +1194,8 @@ namespace System.Management.Automation
|
||||
private enum PreProcessCommandResult
|
||||
{
|
||||
/// <summary>
|
||||
/// No debugger pre-processing.
|
||||
/// No debugger pre-processing. "Get" commands use this so that the
|
||||
/// data they retrieve can be sent back to the caller.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
@@ -1204,11 +1205,6 @@ namespace System.Management.Automation
|
||||
/// </summary>
|
||||
ValidNotProcessed,
|
||||
|
||||
/// <summary>
|
||||
/// GetDebuggerStopArgs.
|
||||
/// </summary>
|
||||
GetDebuggerStopArgs,
|
||||
|
||||
/// <summary>
|
||||
/// SetDebuggerAction.
|
||||
/// </summary>
|
||||
@@ -1227,7 +1223,7 @@ namespace System.Management.Automation
|
||||
/// <summary>
|
||||
/// SetPreserveUnhandledBreakpointMode.
|
||||
/// </summary>
|
||||
SetPreserveUnhandledBreakpointMode
|
||||
SetPreserveUnhandledBreakpointMode,
|
||||
};
|
||||
|
||||
private class DebuggerCommandArgument
|
||||
@@ -1266,35 +1262,31 @@ namespace System.Management.Automation
|
||||
|
||||
var command = commands.Commands[0];
|
||||
string commandText = command.CommandText;
|
||||
if (commandText.Equals(DebuggerUtils.GetDebuggerStopArgsFunctionName, StringComparison.OrdinalIgnoreCase))
|
||||
if (commandText.Equals(RemoteDebuggingCommands.GetDebuggerStopArgs, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
//
|
||||
// __Get-PSDebuggerStopArgs private virtual command.
|
||||
// No input parameters.
|
||||
// Returns DebuggerStopEventArgs object.
|
||||
//
|
||||
|
||||
// Evaluate this command only if the debugger is activated.
|
||||
if (!isDebuggerActive) { return PreProcessCommandResult.ValidNotProcessed; }
|
||||
if (!isDebuggerActive)
|
||||
{
|
||||
return PreProcessCommandResult.ValidNotProcessed;
|
||||
}
|
||||
|
||||
// Translate into debugger method call.
|
||||
ScriptBlock scriptBlock = ScriptBlock.Create("$host.Runspace.Debugger.GetDebuggerStopArgs()");
|
||||
scriptBlock.LanguageMode = PSLanguageMode.FullLanguage;
|
||||
commands.Clear();
|
||||
commands.AddCommand("Invoke-Command").AddParameter("ScriptBlock", scriptBlock).AddParameter("NoNewScope", true);
|
||||
|
||||
result = PreProcessCommandResult.GetDebuggerStopArgs;
|
||||
ReplaceVirtualCommandWithScript(commands, "$host.Runspace.Debugger.GetDebuggerStopArgs()");
|
||||
}
|
||||
else if (commandText.Equals(DebuggerUtils.SetDebuggerActionFunctionName, StringComparison.OrdinalIgnoreCase))
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.SetDebuggerAction, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
//
|
||||
// __Set-PSDebuggerAction private virtual command.
|
||||
// DebuggerResumeAction enum input parameter.
|
||||
// Returns void.
|
||||
//
|
||||
|
||||
// Evaluate this command only if the debugger is activated.
|
||||
if (!isDebuggerActive) { return PreProcessCommandResult.ValidNotProcessed; }
|
||||
if (!isDebuggerActive)
|
||||
{
|
||||
return PreProcessCommandResult.ValidNotProcessed;
|
||||
}
|
||||
|
||||
if ((command.Parameters == null) || (command.Parameters.Count == 0) ||
|
||||
(!command.Parameters[0].Name.Equals("ResumeAction", StringComparison.OrdinalIgnoreCase)))
|
||||
@@ -1313,22 +1305,14 @@ namespace System.Management.Automation
|
||||
catch (InvalidCastException) { }
|
||||
}
|
||||
|
||||
if (resumeAction == null)
|
||||
{
|
||||
throw new PSArgumentException("ResumeAction");
|
||||
}
|
||||
|
||||
commandArgument.ResumeAction = resumeAction;
|
||||
commandArgument.ResumeAction = resumeAction ?? throw new PSArgumentException("ResumeAction");
|
||||
result = PreProcessCommandResult.SetDebuggerAction;
|
||||
}
|
||||
else if (commandText.Equals(DebuggerUtils.SetDebugModeFunctionName, StringComparison.OrdinalIgnoreCase))
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.SetDebugMode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
//
|
||||
// __Set-PSDebugMode private virtual command.
|
||||
// DebugModes enum input parameter.
|
||||
// Returns void.
|
||||
//
|
||||
|
||||
if ((command.Parameters == null) || (command.Parameters.Count == 0) ||
|
||||
(!command.Parameters[0].Name.Equals("Mode", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
@@ -1346,22 +1330,14 @@ namespace System.Management.Automation
|
||||
catch (InvalidCastException) { }
|
||||
}
|
||||
|
||||
if (mode == null)
|
||||
{
|
||||
throw new PSArgumentException("Mode");
|
||||
}
|
||||
|
||||
commandArgument.Mode = mode;
|
||||
commandArgument.Mode = mode ?? throw new PSArgumentException("Mode");
|
||||
result = PreProcessCommandResult.SetDebugMode;
|
||||
}
|
||||
else if (commandText.Equals(DebuggerUtils.SetDebuggerStepMode, StringComparison.OrdinalIgnoreCase))
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.SetDebuggerStepMode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
//
|
||||
// __Set-PSDebuggerStepMode private virtual command.
|
||||
// Boolean Enabled input parameter.
|
||||
// Returns void.
|
||||
//
|
||||
|
||||
if ((command.Parameters == null) || (command.Parameters.Count == 0) ||
|
||||
(!command.Parameters[0].Name.Equals("Enabled", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
@@ -1372,14 +1348,11 @@ namespace System.Management.Automation
|
||||
commandArgument.DebuggerStepEnabled = enabled;
|
||||
result = PreProcessCommandResult.SetDebuggerStepMode;
|
||||
}
|
||||
else if (commandText.Equals(DebuggerUtils.SetPSUnhandledBreakpointMode, StringComparison.OrdinalIgnoreCase))
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.SetUnhandledBreakpointMode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
//
|
||||
// __Set-PSUnhandledBreakpointMode private virtual command.
|
||||
// UnhandledBreakpointMode input parameter.
|
||||
// Returns void.
|
||||
//
|
||||
|
||||
if ((command.Parameters == null) || (command.Parameters.Count == 0) ||
|
||||
(!command.Parameters[0].Name.Equals("UnhandledBreakpointMode", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
@@ -1397,18 +1370,168 @@ namespace System.Management.Automation
|
||||
catch (InvalidCastException) { }
|
||||
}
|
||||
|
||||
if (mode == null)
|
||||
commandArgument.UnhandledBreakpointMode = mode ?? throw new PSArgumentException("Mode");
|
||||
result = PreProcessCommandResult.SetPreserveUnhandledBreakpointMode;
|
||||
}
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.GetBreakpoint, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// __Get-PSBreakpoint private virtual command.
|
||||
// Input parameters:
|
||||
// [-Id <int>]
|
||||
// Returns Breakpoint object(s).
|
||||
string script = null;
|
||||
|
||||
if (command.Parameters?.Count > 0)
|
||||
{
|
||||
throw new PSArgumentException("Mode");
|
||||
int breakpointId = CheckBreakpointIdParameter(command);
|
||||
script = $"$host.Runspace.Debugger.GetBreakpoint({breakpointId})";
|
||||
}
|
||||
else
|
||||
{
|
||||
script = $"$host.Runspace.Debugger.GetBreakpoints()";
|
||||
}
|
||||
|
||||
commandArgument.UnhandledBreakpointMode = mode;
|
||||
result = PreProcessCommandResult.SetPreserveUnhandledBreakpointMode;
|
||||
ReplaceVirtualCommandWithScript(commands, script);
|
||||
}
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.SetBreakpoint, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// __Set-PSBreakpoint private virtual command.
|
||||
// Input parameters:
|
||||
// [-Script] <string[]> [-Line] <int[]> [[-Column] <int>] [-Action <scriptblock>]
|
||||
// [[-Script] <string[]>] -Command <string[]> [-Action <scriptblock>]
|
||||
// [[-Script] <string[]>] -Variable <string[]> [-Action <scriptblock>] [-Mode <VariableAccessMode>]
|
||||
// Returns Breakpoint object.
|
||||
if (command.Parameters == null || command.Parameters.Count == 0)
|
||||
{
|
||||
throw new PSArgumentException("You must provide at least one parameter.");
|
||||
}
|
||||
|
||||
string breakpointType = null;
|
||||
foreach (var commandParameter in command.Parameters)
|
||||
{
|
||||
if (!commandParameter.Name.Equals("Script", StringComparison.OrdinalIgnoreCase) &&
|
||||
!commandParameter.Name.Equals("Line", StringComparison.OrdinalIgnoreCase) &&
|
||||
!commandParameter.Name.Equals("Column", StringComparison.OrdinalIgnoreCase) &&
|
||||
!commandParameter.Name.Equals("Action", StringComparison.OrdinalIgnoreCase) &&
|
||||
!commandParameter.Name.Equals("Command", StringComparison.OrdinalIgnoreCase) &&
|
||||
!commandParameter.Name.Equals("Variable", StringComparison.OrdinalIgnoreCase) &&
|
||||
!commandParameter.Name.Equals("Mode", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new PSArgumentException(commandParameter.Name);
|
||||
}
|
||||
|
||||
if (commandParameter.Name.Equals("Line", StringComparison.OrdinalIgnoreCase) ||
|
||||
commandParameter.Name.Equals("Column", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (breakpointType != null && breakpointType != "Line")
|
||||
{
|
||||
throw new PSArgumentException(commandParameter.Name);
|
||||
}
|
||||
|
||||
breakpointType = "Line";
|
||||
}
|
||||
else if (commandParameter.Name.Equals("Command", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (breakpointType != null)
|
||||
{
|
||||
throw new PSArgumentException(commandParameter.Name);
|
||||
}
|
||||
|
||||
breakpointType = "Command";
|
||||
}
|
||||
else if (commandParameter.Name.Equals("Variable", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (breakpointType != null)
|
||||
{
|
||||
throw new PSArgumentException(commandParameter.Name);
|
||||
}
|
||||
|
||||
breakpointType = "Variable";
|
||||
}
|
||||
}
|
||||
|
||||
commands.Clear();
|
||||
commands.AddCommand("Set-PSBreakpoint");
|
||||
foreach (var commandParameter in command.Parameters)
|
||||
{
|
||||
var parameterValue = commandParameter.Name.Equals("Action", StringComparison.OrdinalIgnoreCase)
|
||||
? ScriptBlock.Create(commandParameter.Value as string)
|
||||
: commandParameter.Value;
|
||||
|
||||
commands.AddParameter(commandParameter.Name, parameterValue);
|
||||
}
|
||||
}
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.RemoveBreakpoint, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// __Remove-PSBreakpoint private virtual command.
|
||||
// Input parameters:
|
||||
// -Id <int>
|
||||
// Returns bool.
|
||||
|
||||
int breakpointId = CheckBreakpointIdParameter(command);
|
||||
|
||||
string script = $"$bp = $host.Runspace.Debugger.GetBreakpoint({breakpointId}); $bp -ne $null -and $host.Runspace.Debugger.RemoveBreakpoint($bp)";
|
||||
|
||||
ReplaceVirtualCommandWithScript(commands, script);
|
||||
}
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.EnableBreakpoint, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// __Enable-PSBreakpoint private virtual command.
|
||||
// Input parameters:
|
||||
// -Id <int>
|
||||
// Returns Breakpoint.
|
||||
|
||||
int breakpointId = CheckBreakpointIdParameter(command);
|
||||
|
||||
string script = $"$bp = $host.Runspace.Debugger.GetBreakpoint({breakpointId}); if ($bp -ne $null) {{$host.Runspace.Debugger.EnableBreakpoint($bp)}}";
|
||||
|
||||
ReplaceVirtualCommandWithScript(commands, script);
|
||||
}
|
||||
else if (commandText.Equals(RemoteDebuggingCommands.DisableBreakpoint, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// __Disable-PSBreakpoint private virtual command.
|
||||
// Input parameters:
|
||||
// -Id <int>
|
||||
// Returns Breakpoint.
|
||||
|
||||
int breakpointId = CheckBreakpointIdParameter(command);
|
||||
|
||||
string script = $"$bp = $host.Runspace.Debugger.GetBreakpoint({breakpointId}); if ($bp -ne $null) {{$host.Runspace.Debugger.DisableBreakpoint($bp)}}";
|
||||
|
||||
ReplaceVirtualCommandWithScript(commands, script);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void ReplaceVirtualCommandWithScript(PSCommand commands, string script)
|
||||
{
|
||||
ScriptBlock scriptBlock = ScriptBlock.Create(script);
|
||||
scriptBlock.LanguageMode = PSLanguageMode.FullLanguage;
|
||||
commands.Clear();
|
||||
commands.AddCommand("Invoke-Command")
|
||||
.AddParameter("ScriptBlock", scriptBlock)
|
||||
.AddParameter("NoNewScope", true);
|
||||
}
|
||||
|
||||
private static int CheckBreakpointIdParameter(Command command)
|
||||
{
|
||||
if (command.Parameters == null ||
|
||||
command.Parameters.Count == 0 ||
|
||||
!command.Parameters[0].Name.Equals("Id", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new PSArgumentException("Id");
|
||||
}
|
||||
|
||||
int? breakpointId = command.Parameters[0].Value as int?;
|
||||
if (breakpointId == null)
|
||||
{
|
||||
throw new PSArgumentException("Id");
|
||||
}
|
||||
|
||||
return breakpointId.Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Classes
|
||||
@@ -1706,28 +1829,30 @@ namespace System.Management.Automation
|
||||
get { return _inDebugMode; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the provided set of breakpoints to the debugger.
|
||||
/// </summary>
|
||||
/// <param name="breakpoints">Breakpoints.</param>
|
||||
public override void SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
|
||||
{
|
||||
_wrappedDebugger.Value.SetBreakpoints(breakpoints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a breakpoint by id, primarily for Enable/Disable/Remove-PSBreakpoint cmdlets.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the breakpoint you want.</param>
|
||||
public override Breakpoint GetBreakpoint(int id) =>
|
||||
_wrappedDebugger.Value.GetBreakpoint(id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns breakpoints primarily for the Get-PSBreakpoint cmdlet.
|
||||
/// </summary>
|
||||
public override List<Breakpoint> GetBreakpoints() =>
|
||||
_wrappedDebugger.Value.GetBreakpoints();
|
||||
|
||||
public override CommandBreakpoint SetCommandBreakpoint(string command, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.Value.SetCommandBreakpoint(command, action, path);
|
||||
|
||||
public override LineBreakpoint SetLineBreakpoint(string path, int line, int column = 0, ScriptBlock action = null) =>
|
||||
_wrappedDebugger.Value.SetLineBreakpoint(path, line, column, action);
|
||||
|
||||
public override VariableBreakpoint SetVariableBreakpoint(string variableName, VariableAccessMode accessMode = VariableAccessMode.Write, ScriptBlock action = null, string path = null) =>
|
||||
_wrappedDebugger.Value.SetVariableBreakpoint(variableName, accessMode, action, path);
|
||||
|
||||
public override bool RemoveBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.Value.RemoveBreakpoint(breakpoint);
|
||||
|
||||
public override Breakpoint EnableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.Value.EnableBreakpoint(breakpoint);
|
||||
|
||||
public override Breakpoint DisableBreakpoint(Breakpoint breakpoint) =>
|
||||
_wrappedDebugger.Value.DisableBreakpoint(breakpoint);
|
||||
|
||||
/// <summary>
|
||||
/// Exits debugger mode with the provided resume action.
|
||||
/// </summary>
|
||||
@@ -1855,13 +1980,15 @@ namespace System.Management.Automation
|
||||
/// Sets up debugger to debug provided job or its child jobs.
|
||||
/// </summary>
|
||||
/// <param name="job">
|
||||
/// Job object that is either a debuggable job or a container
|
||||
/// of debuggable child jobs.
|
||||
/// Job object that is either a debuggable job or a container of
|
||||
/// debuggable child jobs.
|
||||
/// </param>
|
||||
internal override void DebugJob(Job job)
|
||||
{
|
||||
_wrappedDebugger.Value.DebugJob(job);
|
||||
}
|
||||
/// <param name="breakAll">
|
||||
/// If true, the debugger automatically invokes a break all when it
|
||||
/// attaches to the job.
|
||||
/// </param>
|
||||
internal override void DebugJob(Job job, bool breakAll) =>
|
||||
_wrappedDebugger.Value.DebugJob(job, breakAll);
|
||||
|
||||
/// <summary>
|
||||
/// Removes job from debugger job list and pops its
|
||||
@@ -1876,20 +2003,16 @@ namespace System.Management.Automation
|
||||
/// <summary>
|
||||
/// Sets up debugger to debug provided Runspace in a nested debug session.
|
||||
/// </summary>
|
||||
/// <param name="runspace">Runspace to debug.</param>
|
||||
internal override void DebugRunspace(Runspace runspace)
|
||||
/// <param name="runspace">
|
||||
/// Runspace to debug.
|
||||
/// </param>
|
||||
/// <param name="breakAll">
|
||||
/// When true, this command will invoke a BreakAll when the debugger is
|
||||
/// first attached.
|
||||
/// </param>
|
||||
internal override void DebugRunspace(Runspace runspace, bool breakAll)
|
||||
{
|
||||
_wrappedDebugger.Value.DebugRunspace(runspace);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up debugger to debug provided Runspace in a nested debug session.
|
||||
/// </summary>
|
||||
/// <param name="runspace">Runspace to debug.</param>
|
||||
/// <param name="disableBreakAll"></param>
|
||||
internal override void DebugRunspace(Runspace runspace, bool disableBreakAll)
|
||||
{
|
||||
_wrappedDebugger.Value.DebugRunspace(runspace, disableBreakAll);
|
||||
_wrappedDebugger.Value.DebugRunspace(runspace, breakAll);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -237,6 +237,9 @@ The current session does not support debugging; operation will continue.
|
||||
<data name="RemoteServerDebuggerCannotPushSelf" xml:space="preserve">
|
||||
<value>Cannot push a debugger object onto itself.</value>
|
||||
</data>
|
||||
<data name="CommandNotSupportedForRemoteUseInServerDebugger" xml:space="preserve">
|
||||
<value>The {0} command is not supported for remote use in the version of PowerShell that is running in the remote runspace.</value>
|
||||
</data>
|
||||
<data name="NestedRunspaceDebuggerPromptProcessName" xml:space="preserve">
|
||||
<value>Process</value>
|
||||
</data>
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
Describe "Enable and Disable PSBreakpoints" -Tag "CI" {
|
||||
BeforeAll {
|
||||
$path = Setup -F testbp.ps1 -content "get-command`nget-date`nget-location" -pass
|
||||
$bp = set-psbreakpoint -script $path -line 2
|
||||
disable-psbreakpoint $bp
|
||||
}
|
||||
AfterAll {
|
||||
$bp | remove-psbreakpoint
|
||||
}
|
||||
It "Enable-PSBreakpoint should enable the breakpoint" {
|
||||
$bp.Enabled | Should -BeFalse
|
||||
Enable-PSBreakpoint $bp
|
||||
$bp.Enabled | Should -BeTrue
|
||||
}
|
||||
It "Disable-PSBreakpoint should disable the breakpoint" {
|
||||
Enable-PSBreakpoint $bp
|
||||
$bp.Enabled | Should -BeTrue
|
||||
Disable-PSBreakpoint $bp
|
||||
$bp.Enabled | Should -BeFalse
|
||||
}
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
$FeatureEnabled = $EnabledExperimentalFeatures.Contains('Microsoft.PowerShell.Utility.PSDebugRunspaceWithBreakpoints')
|
||||
|
||||
Describe "New-PSBreakpoint Unit Tests - Feature-Enabled" -Tags "CI" {
|
||||
|
||||
BeforeAll {
|
||||
if (!$FeatureEnabled) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'Microsoft.PowerShell.Utility.PSDebugRunspaceWithBreakpoints' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
return
|
||||
}
|
||||
|
||||
#Set up script file 1
|
||||
$scriptFileName1 = Join-Path $TestDrive -ChildPath breakpointTestScript.ps1
|
||||
|
||||
$contents = @"
|
||||
function Hello
|
||||
{
|
||||
`$greeting = 'Hello, world!'
|
||||
write-host `$greeting
|
||||
}
|
||||
|
||||
function Goodbye
|
||||
{
|
||||
`$message = 'Good bye, cruel world!'
|
||||
write-host `$message
|
||||
}
|
||||
|
||||
Hello
|
||||
Goodbye
|
||||
|
||||
# The following 2 statements produce null tokens (needed to verify 105473)
|
||||
#
|
||||
`$table = @{}
|
||||
|
||||
return
|
||||
"@
|
||||
|
||||
$contents > $scriptFileName1
|
||||
|
||||
# Set up script file 2
|
||||
$scriptFileName2 = Join-Path -Path $TestDrive -ChildPath psbreakpointtestscript.ps1
|
||||
|
||||
"`$var = 1 " > $scriptFileName2
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if (!$FeatureEnabled) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
It "Should be able to set psbreakpoints for -Line" {
|
||||
$brk = New-PSBreakpoint -Line 13 -Script $scriptFileName1
|
||||
$brk.Line | Should -Be 13
|
||||
}
|
||||
|
||||
It "Should be able to set psbreakpoints for -Line and -column" {
|
||||
$brk = New-PSBreakpoint -line 13 -column 1 -script $scriptFileName1
|
||||
$brk.Line | Should -Be 13
|
||||
$brk.Column | Should -Be 1
|
||||
}
|
||||
|
||||
It "Should be able to set psbreakpoints for -Line and -action" {
|
||||
$brk = New-PSBreakpoint -line 13 -action {{ break; }} -script $scriptFileName1
|
||||
$brk.Line | Should -Be 13
|
||||
$brk.Action | Should -Match "break"
|
||||
}
|
||||
|
||||
It "Should be able to set psbreakpoints for -Line, -column and -action" {
|
||||
$brk = New-PSBreakpoint -line 13 -column 1 -action {{ break; }} -script $scriptFileName1
|
||||
$brk.Line | Should -Be 13
|
||||
$brk.Column | Should -Be 1
|
||||
$brk.Action | Should -Match "break"
|
||||
}
|
||||
|
||||
It "-script and -line can take multiple items" {
|
||||
$brk = New-PSBreakpoint -line 11,12,13 -column 1 -script $scriptFileName1,$scriptFileName1
|
||||
$brk.Line | Should -BeIn 11,12,13
|
||||
$brk.Column | Should -BeIn 1
|
||||
}
|
||||
|
||||
It "-script and -line are positional" {
|
||||
$brk = New-PSBreakpoint $scriptFileName1 13
|
||||
$brk.Line | Should -Be 13
|
||||
}
|
||||
|
||||
It "-script, -line and -column are positional" {
|
||||
$brk = New-PSBreakpoint $scriptFileName1 13 1
|
||||
$brk.Line | Should -Be 13
|
||||
$brk.Column | Should -Be 1
|
||||
}
|
||||
|
||||
It "Should throw Exception when missing mandatory parameter -line" -Pending {
|
||||
$output = pwsh -noninteractive -command "nbp -column 1 -script $scriptFileName1"
|
||||
[system.string]::Join(" ", $output) | Should -Match "MissingMandatoryParameter,Microsoft.PowerShell.Commands.NewPSBreakpointCommand"
|
||||
}
|
||||
|
||||
It "Should throw Exception when missing mandatory parameter" -Pending {
|
||||
$output = pwsh -noprofile -noninteractive -command "nbp -line 1"
|
||||
[system.string]::Join(" ", $output) | Should -Match "MissingMandatoryParameter,Microsoft.PowerShell.Commands.NewPSBreakpointCommand"
|
||||
}
|
||||
|
||||
It "Should be able to set psbreakpoints for -command" {
|
||||
$brk = New-PSBreakpoint -command "write-host"
|
||||
$brk.Command | Should -BeExactly "write-host"
|
||||
}
|
||||
|
||||
It "Should be able to set psbreakpoints for -command, -script" {
|
||||
$brk = New-PSBreakpoint -command "write-host" -script $scriptFileName1
|
||||
$brk.Command | Should -BeExactly "write-host"
|
||||
}
|
||||
|
||||
It "Should be able to set psbreakpoints for -command, -action and -script" {
|
||||
$brk = New-PSBreakpoint -command "write-host" -action {{ break; }} -script $scriptFileName1
|
||||
$brk.Action | Should -Match "break"
|
||||
}
|
||||
|
||||
It "-Command can take multiple items" {
|
||||
$brk = New-PSBreakpoint -command write-host,Hello
|
||||
$brk.Command | Should -Be write-host,Hello
|
||||
}
|
||||
|
||||
It "-Script is positional" {
|
||||
$brk = New-PSBreakpoint -command "Hello" $scriptFileName1
|
||||
$brk.Command | Should -BeExactly "Hello"
|
||||
|
||||
$brk = New-PSBreakpoint $scriptFileName1 -command "Hello"
|
||||
$brk.Command | Should -BeExactly "Hello"
|
||||
}
|
||||
|
||||
It "Should be able to set breakpoints on functions" {
|
||||
$brk = New-PSBreakpoint -command Hello,Goodbye -script $scriptFileName1
|
||||
$brk.Command | Should -Be Hello,Goodbye
|
||||
}
|
||||
|
||||
It "Should be throw Exception when Column number less than 1" {
|
||||
{ New-PSBreakpoint -line 1 -column -1 -script $scriptFileName1 } | Should -Throw -ErrorId "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewPSBreakpointCommand"
|
||||
}
|
||||
|
||||
It "Should be throw Exception when Line number less than 1" {
|
||||
$ErrorActionPreference = "Stop"
|
||||
{ New-PSBreakpoint -line -1 -script $scriptFileName1 } | Should -Throw -ErrorId "NewPSBreakpoint:LineLessThanOne,Microsoft.PowerShell.Commands.NewPSBreakpointCommand"
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
}
|
||||
|
||||
It "Fail to set psbreakpoints when script is a file of wrong type" {
|
||||
$tempFile = [System.IO.Path]::GetTempFileName()
|
||||
$ErrorActionPreference = "Stop"
|
||||
{
|
||||
New-PSBreakpoint -Script $tempFile -Line 1
|
||||
} | Should -Throw
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
Remove-Item $tempFile -Force
|
||||
}
|
||||
|
||||
It "Fail to set psbreakpoints when script file does not exist" {
|
||||
$ErrorActionPreference = "Stop"
|
||||
${script.ps1} = 10
|
||||
{
|
||||
New-PSBreakpoint -Script variable:\script.ps1 -Line 1
|
||||
} | Should -Throw
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
}
|
||||
|
||||
It "Should be able to set a psbreakpoint on a line" {
|
||||
$lineNumber = 1
|
||||
$brk = New-PSBreakpoint -Line $lineNumber -Script $scriptFileName2
|
||||
$brk.Line | Should -Be $lineNumber
|
||||
}
|
||||
|
||||
It "Should throw when a string is entered for a line number" {
|
||||
{
|
||||
$lineNumber = "one"
|
||||
New-PSBreakpoint -Line $lineNumber -Script $scriptFileName2
|
||||
|
||||
} | Should -Throw
|
||||
}
|
||||
|
||||
It "Should be able to set a psbreakpoint on a Command" {
|
||||
$command = "theCommand"
|
||||
$brk = New-PSBreakpoint -Command $command -Script $scriptFileName2
|
||||
$brk.Command | Should -Be $command
|
||||
}
|
||||
|
||||
It "Should be able to set a psbreakpoint on a variable" {
|
||||
$var = "theVariable"
|
||||
$brk = New-PSBreakpoint -Command $var -Script $scriptFileName2
|
||||
$brk.Command | Should -Be $var
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe 'Breakpoint SDK Unit Tests' -Tags 'CI' {
|
||||
|
||||
BeforeAll {
|
||||
# Start a job; this will create a runspace in which we can manage breakpoints
|
||||
$job = Start-Job -ScriptBlock {
|
||||
Set-PSBreakpoint -Command Start-Sleep
|
||||
1..240 | ForEach-Object {
|
||||
Start-Sleep -Milliseconds 250
|
||||
$_
|
||||
Write-Error 'boo'
|
||||
Write-Verbose 'Verbose' -Verbose
|
||||
$DebugPreference = 'Continue'
|
||||
Write-Debug 'Debug'
|
||||
Write-Warning 'Warning'
|
||||
}
|
||||
}
|
||||
|
||||
# Wait for the child job that gets created to hit the breakpoint. This is the
|
||||
# only safe way to know that the job has actually entered a running state and
|
||||
# that the remote runspace is listening for requests.
|
||||
Wait-UntilTrue { $job.ChildJobs.Count -gt 0 -and $job.ChildJobs[0].State -eq 'AtBreakpoint' } -TimeoutInMilliseconds 10000 -IntervalInMilliseconds 250
|
||||
|
||||
# Get the runspace for the running job
|
||||
$jobRunspace = $job.ChildJobs[0].Runspace
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
# Remove the running job forcibly (whether it has finished or not)
|
||||
Remove-Job -Job $job -Force
|
||||
}
|
||||
|
||||
Context 'Managing breakpoints in the host runspace via the SDK' {
|
||||
|
||||
It 'Can set command breakpoints' {
|
||||
$host.Runspace.Debugger.SetCommandBreakpoint('Test-ThisCommandDoesNotExist') | Should -BeOfType [System.Management.Automation.CommandBreakpoint]
|
||||
}
|
||||
|
||||
It 'Can set variable breakpoints' {
|
||||
$host.Runspace.Debugger.SetVariableBreakpoint('DebugPreference', 'ReadWrite', { continue }) | Should -BeOfType [System.Management.Automation.VariableBreakpoint]
|
||||
}
|
||||
|
||||
It 'Can set line breakpoints' {
|
||||
$host.Runspace.Debugger.SetLineBreakpoint($PSCommandPath, 1, 1, { continue }) | Should -BeOfType [System.Management.Automation.LineBreakpoint]
|
||||
}
|
||||
|
||||
It 'Can get breakpoints' {
|
||||
$host.Runspace.Debugger.GetBreakpoints() | Should -HaveCount 3
|
||||
}
|
||||
|
||||
It 'Can disable breakpoints' {
|
||||
foreach ($bp in $host.Runspace.Debugger.GetBreakpoints()) {
|
||||
$bp = $host.Runspace.Debugger.DisableBreakpoint($bp)
|
||||
$bp.Enabled | Should -BeFalse
|
||||
}
|
||||
}
|
||||
|
||||
It 'Can enable breakpoints' {
|
||||
foreach ($bp in $host.Runspace.Debugger.GetBreakpoints()) {
|
||||
$bp = $host.Runspace.Debugger.EnableBreakpoint($bp)
|
||||
$bp.Enabled | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
It 'Can remove breakpoints' {
|
||||
foreach ($bp in $host.Runspace.Debugger.GetBreakpoints()) {
|
||||
$host.Runspace.Debugger.RemoveBreakpoint($bp) | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
It 'Returns an empty collection when there are no breakpoints' {
|
||||
$host.Runspace.Debugger.GetBreakpoints() | Should -HaveCount 0
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Managing breakpoints in a remote runspace via the SDK' {
|
||||
|
||||
AfterAll {
|
||||
# Get rid of any breakpoints that were created in the default runspace.
|
||||
# This is necessary due to a known bug that causes breakpoints with the
|
||||
# same id to be created or updated in the default runspace.
|
||||
Get-PSBreakpoint | Remove-PSBreakpoint
|
||||
}
|
||||
|
||||
It 'Can set command breakpoints' {
|
||||
$jobRunspace.Debugger.SetCommandBreakpoint('Write-Verbose', { break }) | Should -BeOfType [System.Management.Automation.CommandBreakpoint]
|
||||
}
|
||||
|
||||
It 'Can set variable breakpoints' {
|
||||
$jobRunspace.Debugger.SetVariableBreakpoint('DebugPreference', 'ReadWrite', { break }) | Should -BeOfType [System.Management.Automation.VariableBreakpoint]
|
||||
}
|
||||
|
||||
It 'Can set line breakpoints' {
|
||||
$jobRunspace.Debugger.SetLineBreakpoint($PSCommandPath, 1, 1, { break }) | Should -BeOfType [System.Management.Automation.LineBreakpoint]
|
||||
}
|
||||
|
||||
It 'Can get breakpoints' {
|
||||
# This is 4, not 3, because we set a breakpoint in our job script
|
||||
$jobRunspace.Debugger.GetBreakpoints() | Should -HaveCount 4
|
||||
}
|
||||
|
||||
It 'Can disable breakpoints' {
|
||||
foreach ($bp in $jobRunspace.Debugger.GetBreakpoints()) {
|
||||
$bp = $jobRunspace.Debugger.DisableBreakpoint($bp)
|
||||
$bp.Enabled | Should -BeFalse
|
||||
}
|
||||
}
|
||||
|
||||
It 'Can enable breakpoints' {
|
||||
foreach ($bp in $jobRunspace.Debugger.GetBreakpoints()) {
|
||||
$bp = $jobRunspace.Debugger.EnableBreakpoint($bp)
|
||||
$bp.Enabled | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
It 'Can remove breakpoints' {
|
||||
foreach ($bp in $jobRunspace.Debugger.GetBreakpoints()) {
|
||||
$jobRunspace.Debugger.RemoveBreakpoint($bp) | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
It 'Returns an empty collection when there are no breakpoints' {
|
||||
$jobRunspace.Debugger.GetBreakpoints() | Should -HaveCount 0
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Handling empty collections and errors while managing breakpoints in the host runspace via the SDK' {
|
||||
|
||||
BeforeAll {
|
||||
$bp = $host.Runspace.Debugger.SetCommandBreakpoint('Test-ThisCommandDoesNotExist')
|
||||
$host.Runspace.Debugger.RemoveBreakpoint($bp) > $null
|
||||
}
|
||||
|
||||
It 'Returns false when trying to disable a breakpoint that does not exist' {
|
||||
$host.Runspace.Debugger.DisableBreakpoint($bp) | Should -Be $null
|
||||
}
|
||||
|
||||
It 'Returns false when trying to enable a breakpoint that does not exist' {
|
||||
$host.Runspace.Debugger.EnableBreakpoint($bp) | Should -Be $null
|
||||
}
|
||||
|
||||
It 'Returns false when trying to remove a breakpoint that does not exist' {
|
||||
$host.Runspace.Debugger.RemoveBreakpoint($bp) | Should -BeFalse
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Handling errors while managing breakpoints in a remote runspace via the SDK' {
|
||||
|
||||
BeforeAll {
|
||||
$bp = $jobRunspace.Debugger.SetCommandBreakpoint('Test-ThisCommandDoesNotExist')
|
||||
$jobRunspace.Debugger.RemoveBreakpoint($bp) > $null
|
||||
}
|
||||
|
||||
It 'Returns false when trying to disable a breakpoint that does not exist' {
|
||||
$jobRunspace.Debugger.DisableBreakpoint($bp) | Should -Be $null
|
||||
}
|
||||
|
||||
It 'Returns false when trying to enable a breakpoint that does not exist' {
|
||||
$jobRunspace.Debugger.EnableBreakpoint($bp) | Should -Be $null
|
||||
}
|
||||
|
||||
It 'Returns false when trying to remove a breakpoint that does not exist' {
|
||||
$jobRunspace.Debugger.RemoveBreakpoint($bp) | Should -BeFalse
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,6 @@ Describe "Verify approved aliases list" -Tags "CI" {
|
||||
"Alias", "move", "Move-Item", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "AllScope", ""
|
||||
"Alias", "mp", "Move-ItemProperty", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "mv", "Move-Item", $($FullCLR -or $CoreWindows ), "", "", ""
|
||||
"Alias", "nbp", "New-PSBreakpoint", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "nal", "New-Alias", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "ndr", "New-PSDrive", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "ni", "New-Item", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"ExperimentalFeatures": {
|
||||
"Microsoft.PowerShell.Utility.PSDebugRunspaceWithBreakpoints": ["test/powershell/Modules/Microsoft.PowerShell.Utility/New-PSBreakpoint.Tests.ps1"],
|
||||
"ExpTest.FeatureOne": [ "test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1" ],
|
||||
"PSForEachObjectParallel": [ "test/powershell/Modules/Microsoft.PowerShell.Utility/Foreach-Object-Parallel.Tests.ps1", "test/powershell/Modules/Microsoft.PowerShell.Security/ConstrainedLanguageRestriction.Tests.ps1" ]
|
||||
}
|
||||
|
||||
@@ -101,31 +101,5 @@ namespace PSTests.Sequential
|
||||
runspace.Close();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestRunspaceSetBreakpoints()
|
||||
{
|
||||
using (var runspace = RunspaceFactory.CreateRunspace())
|
||||
{
|
||||
var expectedBreakpoints = new Breakpoint[] {
|
||||
new LineBreakpoint(@"./path/to/some/file.ps1", 1),
|
||||
new CommandBreakpoint(@"./path/to/some/file.ps1", new WildcardPattern("Write-Host"), "Write-Host"),
|
||||
};
|
||||
|
||||
runspace.Open();
|
||||
|
||||
try
|
||||
{
|
||||
runspace.Debugger.SetBreakpoints(expectedBreakpoints);
|
||||
List<Breakpoint> actualBreakpoints = runspace.Debugger.GetBreakpoints();
|
||||
Assert.Equal(expectedBreakpoints.Length, actualBreakpoints.Count);
|
||||
Assert.Equal(expectedBreakpoints, actualBreakpoints);
|
||||
}
|
||||
finally
|
||||
{
|
||||
runspace.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user