/// <summary> /// Constructor /// </summary> /// <param name="runspace">Associated remote runspace</param> public RemoteDebugger(RemoteRunspace runspace) { if (runspace == null) { throw new PSArgumentNullException("runspace"); } _runspace = runspace; _unhandledBreakpointMode = UnhandledBreakpointProcessingMode.Ignore; // Hook up remote debugger forwarded event handlers. _runspace.RemoteDebuggerStop += HandleForwardedDebuggerStopEvent; _runspace.RemoteDebuggerBreakpointUpdated += HandleForwardedDebuggerBreakpointUpdatedEvent; }
/// <summary> /// Sets client debug info state based on server info. /// </summary> /// <param name="debugMode">Debug mode</param> /// <param name="inBreakpoint">Currently in breakpoint</param> /// <param name="breakpointCount">Breakpoint count</param> /// <param name="breakAll">Break All setting</param> /// <param name="unhandledBreakpointMode">UnhandledBreakpointMode</param> /// <param name="serverPSVersion">Server PowerShell version</param> internal void SetClientDebugInfo( DebugModes? debugMode, bool inBreakpoint, int breakpointCount, bool breakAll, UnhandledBreakpointProcessingMode unhandledBreakpointMode, Version serverPSVersion) { if (debugMode != null) { _remoteDebugSupported = true; DebugMode = debugMode.Value; } else { _remoteDebugSupported = false; } if (inBreakpoint) { SetRemoteDebug(true, RunspaceAvailability.RemoteDebug); } _serverPSVersion = serverPSVersion; _breakpointCount = breakpointCount; _isDebuggerSteppingEnabled = breakAll; _unhandledBreakpointMode = unhandledBreakpointMode; SetIsActive(breakpointCount); }
private DebuggerCommandResults ProcessCommandForActiveDebugger(PSCommand command, PSDataCollection<PSObject> output) { // Check for debugger "detach" command which is only applicable to nested debugging. bool detachCommand = ((command.Commands.Count > 0) && ((command.Commands[0].CommandText.Equals("Detach", StringComparison.OrdinalIgnoreCase)) || (command.Commands[0].CommandText.Equals("d", StringComparison.OrdinalIgnoreCase)))); Debugger activeDebugger; if (_activeDebuggers.TryPeek(out activeDebugger)) { if (detachCommand) { // Exit command means to cancel the nested debugger session. This needs to be done by the // owner of the session so we raise an event and release the debugger stop. UnhandledBreakpointMode = UnhandledBreakpointProcessingMode.Ignore; RaiseNestedDebuggingCancelEvent(); return new DebuggerCommandResults(DebuggerResumeAction.Continue, true); } else if ((command.Commands.Count > 0) && (command.Commands[0].CommandText.IndexOf(".EnterNestedPrompt()", StringComparison.OrdinalIgnoreCase) > 0)) { // Prevent a host EnterNestedPrompt() call from occuring in an active debugger. // Host nested prompt makes no sense in this case and can cause hangs depending on host implementation. throw new PSNotSupportedException(); } // Get current debugger stop breakpoint info. DebuggerStopEventArgs stopArgs; if (_debuggerStopEventArgs.TryPeek(out stopArgs)) { string commandText = command.Commands[0].CommandText; // Check to see if this is a resume command that we handle here. DebuggerCommand dbgCommand = _commandProcessor.ProcessBasicCommand(commandText); if (dbgCommand != null && dbgCommand.ResumeAction != null) { _lastActiveDebuggerAction = dbgCommand.ResumeAction.Value; return new DebuggerCommandResults(dbgCommand.ResumeAction, true); } // If active debugger is Workflow debugger then process command here (for "list" and "help"). if (activeDebugger.GetType().FullName.Equals("Microsoft.PowerShell.Workflow.PSWorkflowDebugger", StringComparison.OrdinalIgnoreCase)) { DebuggerCommand results = _commandProcessor.ProcessCommand(null, commandText, stopArgs.InvocationInfo, output); if ((results != null) && results.ExecutedByDebugger) { return new DebuggerCommandResults(results.ResumeAction, true); } } } return activeDebugger.ProcessCommand(command, output); } if (detachCommand) { // Detach command only applies to nested debugging. So if there isn't any active debugger then emit error. throw new PSInvalidOperationException(DebuggerStrings.InvalidDetachCommand); } return null; }