/// <summary> /// Used to verify attachment to a runspace /// </summary> /// <param name="preScenario">The debug scenario before invoking Enter-PSHostProcess</param> /// <returns>Empty string if attachment was verified, string describing the result otherwise</returns> public string VerifyAttachToRunspace(DebugScenario preScenario, AutoResetEvent attachSemaphore) { if (preScenario != DebugScenario.RemoteSession) { // for local attach, we have to wait for the runspace to be pushed bool didTimeout = !(attachSemaphore.WaitOne(DebugEngineConstants.AttachRequestEventTimeout)); if (didTimeout) { // if semaphore times out, check to see if runspace looks ok, if it does then we will move forward if (_debuggingService.GetDebugScenario() != DebugScenario.LocalAttach) { ServiceCommon.Log("Unable to attach to local process. Semaphore timed out and runspace is confirmed to not be local attach."); return(Resources.ProcessAttachFailErrorBody); } } } else { // if remote attaching, make sure that we are still in a remote session after entering the host DebugScenario scenario = _debuggingService.GetDebugScenario(); if (scenario != DebugScenario.RemoteSession) { ServiceCommon.Log("Failed to attach to remote process; scenario after invoke: {0}", scenario); return(Resources.ProcessAttachFailErrorBody); } } return(string.Empty); }
public void SetupScenario() { switch (currentScenario) { case DebugScenarioType.NEW_USER: //all items locked but one case DebugScenarioType.NEW_USER_RICH: //all items unlocked but one { DebugScenario scenario = scenarios.Find(a => a.scenarioType == currentScenario); GameManager.Instance.Debug_NewUserScenario(); GameManager.Instance.Debug_AddCurrency(scenario.initialCurrencies); } break; case DebugScenarioType.ALL_UNLOCKED: //all items unlocked but one { DebugScenario scenario = scenarios.Find(a => a.scenarioType == currentScenario); GameManager.Instance.Debug_UnlockAllItems(); GameManager.Instance.Debug_AddCurrency(scenario.initialCurrencies); } break; case DebugScenarioType.CUSTOM: break; case DebugScenarioType.NONE: break; default: break; } }
/// <summary> /// Used to verify detachment from a runspace /// </summary> /// <param name="preScenario">The debug scenario before invoking Exit-PSHostProcess</param> /// <returns>True if the detachment was verified, false otherwise</returns> public bool VerifyDetachFromRunspace(DebugScenario preScenario, AutoResetEvent attachSemaphore) { // wait for invoke to finish swapping the runspaces if detaching from a local process if (preScenario == DebugScenario.LocalAttach) { bool didTimeout = !(attachSemaphore.WaitOne(DebugEngineConstants.AttachRequestEventTimeout)); if (didTimeout) { // if semaphore times out, check to see if runspace looks ok, if it does then we will move forward if (_debuggingService.GetDebugScenario() != DebugScenario.Local) { ServiceCommon.Log("Failed to detach from local process. Semaphore timed out and runspace is confirmed to not be local."); return(false); } } } else { // if remote attaching, make sure that we are still in a remote session after exiting the host DebugScenario scenario = _debuggingService.GetDebugScenario(); if (scenario != DebugScenario.RemoteSession) { ServiceCommon.Log(string.Format("Failed to detach from remote process; scenario after invoke: {0}", scenario)); return(false); } } return(true); }
/// <summary> /// Execute the current program node. /// </summary> /// <remarks> /// The node will either be a script file or script content; depending on the node /// passed to this function. /// </remarks> /// <param name="node"></param> public void Execute(ScriptProgramNode node) { CurrentExecutingNode = node; if (node.IsAttachedProgram) { string result = string.Empty; if (!node.IsRemoteProgram) { result = DebuggingService.AttachToRunspace(node.Process.ProcessId); } else { result = DebuggingService.AttachToRemoteRunspace(node.Process.ProcessId, node.Process.HostName); } if (!string.IsNullOrEmpty(result)) { // if either of the attaches returns an error, let the user know MessageBox.Show(result, Resources.AttachErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); // see what state we are in post error, if not in a local state, we need to try and get there DebugScenario postCleanupScenario = DebuggingService.GetDebugScenario(); // try as hard as we can to detach/cleanup the mess for the length of CleanupRetryTimeout TimeSpan retryTimeSpan = TimeSpan.FromMilliseconds(DebugEngineConstants.CleanupRetryTimeout); Stopwatch timeElapsed = Stopwatch.StartNew(); while (timeElapsed.Elapsed < retryTimeSpan && postCleanupScenario != DebugScenario.Local) { postCleanupScenario = DebuggingService.CleanupAttach(); } // if our efforts to cleanup the mess were unsuccessful, inform the user if (postCleanupScenario != DebugScenario.Local) { MessageBox.Show(Resources.CleanupErrorMessage, Resources.DetachErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } RefreshPrompt(); DebuggerFinished(); } } else { string commandLine = node.FileName; if (node.IsFile) { commandLine = String.Format(DebugEngineConstants.ExecutionCommandFormat, node.FileName, node.Arguments); HostUi.VsOutputString(string.Format("{0}{1}{2}", GetPrompt(), node.FileName, Environment.NewLine)); } Execute(commandLine); } }
public void RemoteRunspaceDetachScenarioInvalid() { _preScenario = DebugScenario.RemoteAttach; var debuggingService = new Mock <IPowerShellDebuggingService>(); debuggingService.Setup(m => m.GetDebugScenario()).Returns(DebugScenario.RemoteAttach); _attachUtilities.DebuggingService = debuggingService.Object; _boolResult = _attachUtilities.VerifyDetachFromRunspace(_preScenario, _attachSemaphore); Assert.IsFalse(_boolResult); }
public void RemoteRunspaceAttachScenarioInvalid() { _preScenario = DebugScenario.RemoteSession; var debuggingService = new Mock <IPowerShellDebuggingService>(); debuggingService.Setup(m => m.GetDebugScenario()).Returns(DebugScenario.Local); _attachUtilities.DebuggingService = debuggingService.Object; _stringResult = _attachUtilities.VerifyAttachToRunspace(_preScenario, _attachSemaphore); Assert.IsFalse(string.IsNullOrEmpty(_stringResult)); }
public void LocalRunspaceDetachSemaFailScenarioValid() { _attachSemaphore.Reset(); _preScenario = DebugScenario.LocalAttach; var debuggingService = new Mock <IPowerShellDebuggingService>(); debuggingService.Setup(m => m.GetDebugScenario()).Returns(DebugScenario.Local); _attachUtilities.DebuggingService = debuggingService.Object; _boolResult = _attachUtilities.VerifyDetachFromRunspace(_preScenario, _attachSemaphore); Assert.IsTrue(_boolResult); }
public void LocalRunspaceAttachSemaFailScenarioValid() { _attachSemaphore.Reset(); _preScenario = DebugScenario.Local; var debuggingService = new Mock <IPowerShellDebuggingService>(); debuggingService.Setup(m => m.GetDebugScenario()).Returns(DebugScenario.LocalAttach); _attachUtilities.DebuggingService = debuggingService.Object; _stringResult = _attachUtilities.VerifyAttachToRunspace(_preScenario, _attachSemaphore); Assert.IsTrue(string.IsNullOrEmpty(_stringResult)); }
/// <summary> /// Used by OpenFileInVS to determine correct error message to display if it is unable to open a file /// </summary> /// <param name="scenario"></param> /// <returns></returns> public static string ScenarioToFileOpenErrorMsg(DebugScenario scenario) { switch (scenario) { case DebugScenario.Local: return(Resources.LocalFileOpenError); case DebugScenario.RemoteSession: return(Resources.RemoteSessionFileOpenError); case DebugScenario.LocalAttach: return(Resources.LocalAttachFileOpenError); case DebugScenario.RemoteAttach: return(Resources.RemoteAttachFileOpenError); default: return(Resources.DefaultFileOpenError); } }
public int Detach() { Log.Debug("ScriptProgramNode: Entering Detach"); DebugScenario scenario = Debugger.DebuggingService.GetDebugScenario(); bool result = (scenario == DebugScenario.Local); if (scenario == DebugScenario.LocalAttach) { result = Debugger.DebuggingService.DetachFromRunspace(); } else if (scenario == DebugScenario.RemoteAttach) { result = Debugger.DebuggingService.DetachFromRemoteRunspace(); } if (!result) { // try as hard as we can to detach/cleanup the mess for the length of CleanupRetryTimeout TimeSpan retryTimeSpan = TimeSpan.FromMilliseconds(DebugEngineConstants.CleanupRetryTimeout); Stopwatch timeElapsed = Stopwatch.StartNew(); while (timeElapsed.Elapsed < retryTimeSpan && !result) { result = (Debugger.DebuggingService.CleanupAttach() == DebugScenario.Local); } } if (result) { Debugger.DebuggerFinished(); Debugger.RefreshPrompt(); } return(result ? VSConstants.S_OK : VSConstants.S_FALSE); }
/// <summary> /// PS debugger stopped event handler /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Debugger_DebuggerStop(object sender, DebuggerStopEventArgs e) { ServiceCommon.Log("Debugger stopped ..."); DebugScenario currScenario = GetDebugScenario(); if (_installedPowerShellVersion < RequiredPowerShellVersionForRemoteSessionDebugging) { RefreshScopedVariable(); RefreshCallStack(); } else { RefreshScopedVariable40(); RefreshCallStack40(); } ServiceCommon.LogCallbackEvent("Callback to client, and wait for debuggee to resume"); if (e.Breakpoints.Count > 0) { LineBreakpoint bp = (LineBreakpoint)e.Breakpoints[0]; if (_callback != null) { string file = bp.Script; if (currScenario != DebugScenario.Local && _mapRemoteToLocal.ContainsKey(bp.Script)) { file = _mapRemoteToLocal[bp.Script]; } // breakpoint is always hit for this case _callback.DebuggerStopped(new DebuggerStoppedEventArgs(file, bp.Line, bp.Column, true, false)); } } else { if (_callback != null) { string file; int lineNum, column; switch (currScenario) { case DebugScenario.LocalAttach: file = e.InvocationInfo.ScriptName; lineNum = e.InvocationInfo.ScriptLineNumber; column = e.InvocationInfo.OffsetInLine; // the stop which occurs after attaching is not associated with a breakpoint and should result in the process' script being opened _callback.DebuggerStopped(new DebuggerStoppedEventArgs(file, lineNum, column, false, true)); break; case DebugScenario.RemoteAttach: // copy the remote file over to host machine file = OpenRemoteAttachedFile(e.InvocationInfo.ScriptName); lineNum = e.InvocationInfo.ScriptLineNumber; column = e.InvocationInfo.OffsetInLine; // the stop which occurs after attaching is not associated with a breakpoint and should result in the remote process' script being opened _callback.DebuggerStopped(new DebuggerStoppedEventArgs(file, lineNum, column, false, true)); _needToCopyRemoteScript = false; break; default: _callback.DebuggerStopped(new DebuggerStoppedEventArgs()); break; } } } bool resumed = false; while (!resumed) { _pausedEvent.WaitOne(); try { currScenario = GetDebugScenario(); if (!string.IsNullOrEmpty(_debuggingCommand)) { if (currScenario == DebugScenario.Local) { // local debugging var output = new Collection <PSObject>(); using (var pipeline = (_runspace.CreateNestedPipeline())) { pipeline.Commands.AddScript(_debuggingCommand); pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); output = pipeline.Invoke(); } ProcessDebuggingCommandResults(output); } else { // remote session and local attach debugging ProcessRemoteDebuggingCommandResults(ExecuteDebuggingCommand()); } } else { ServiceCommon.Log(string.Format("Debuggee resume action is {0}", _resumeAction)); e.ResumeAction = _resumeAction; resumed = true; // debugger resumed executing } } catch (Exception ex) { NotifyOutputString(ex.Message); } // Notify the debugging command execution call that debugging command was complete. _debugCommandEvent.Set(); } }
/// <summary> /// Asks HostService to find all attachable processes on the given machine. Will prompt user to retry connecting if /// the call to EnumerateRemoteProcesses returns null. /// </summary> /// <param name="remotePort"></param> public void connect(IDebugPort2 remotePort, bool useSSL) { // Make sure user is starting from a local scenario DebugScenario scenario = PowerShellToolsPackage.Debugger.DebuggingService.GetDebugScenario(); if (scenario != DebugScenario.Local) { Log.Debug(string.Format("User is trying to remote attach while already in {0}", scenario)); if (scenario == DebugScenario.RemoteSession) { MessageBox.Show(Resources.AttachExistingRemoteError, Resources.AttachErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { MessageBox.Show(Resources.AttachExistingAttachError, Resources.AttachErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { // host needs to be initialized before we can connect/enumerate UiContextUtilities.ActivateUiContext(UiContextUtilities.CreateUiContext(Constants.PowerShellReplCreationUiContextGuid)); if (!PowerShellToolsPackage.PowerShellHostInitialized) { // TODO: UI Work required to give user inidcation that it is waiting for debugger to get alive. PowerShellToolsPackage.DebuggerReadyEvent.WaitOne(); } List <KeyValuePair <uint, string> > information; string errorMessage = string.Empty; while (true) { Log.Debug(string.Format("Attempting to find processes on {0}.", _remoteComputer)); information = PowerShellToolsPackage.Debugger.DebuggingService.EnumerateRemoteProcesses(_remoteComputer, ref errorMessage, useSSL); if (information != null) { // information now contains list of processes break; } else if (string.IsNullOrEmpty(errorMessage)) { // user hit cancel return; } else { // error message was returned DialogResult dlgRes = MessageBox.Show(errorMessage, null, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error); if (dlgRes != DialogResult.Retry) { return; } } } foreach (KeyValuePair <uint, string> info in information) { _runningProcesses.Add(new ScriptDebugProcess(remotePort, info.Key, info.Value, _remoteComputer)); } } }