private void ExitNestedPromptHelper() { this.nestedPromptCount--; this.executionContext.SetVariable(SpecialVariables.NestedPromptCounterVarPath, this.nestedPromptCount); if (this.contextStack.Count > 0) { PromptContextData data = this.contextStack.Pop(); data.SavedContextData.RestoreContextData(this.executionContext); this.executionContext.LanguageMode = data.LanguageMode; this.executionContext.SetVariable(SpecialVariables.CurrentlyExecutingCommandVarPath, data.SavedCurrentlyExecutingCommandVarValue); this.executionContext.SetVariable(SpecialVariables.PSBoundParametersVarPath, data.SavedPSBoundParametersVarValue); this.Context.CurrentRunspace.UpdateRunspaceAvailability(data.RunspaceAvailability, true); } }
private void ExitNestedPromptHelper() { --NestedPromptCount; Context.SetVariable(SpecialVariables.NestedPromptCounterVarPath, NestedPromptCount); // restore the saved context Dbg.Assert(_contextStack.Count > 0, "ExitNestedPrompt: called without any saved context"); if (_contextStack.Count > 0) { PromptContextData pcd = _contextStack.Pop(); pcd.SavedContextData.RestoreContextData(Context); Context.LanguageMode = pcd.LanguageMode; Context.SetVariable(SpecialVariables.CurrentlyExecutingCommandVarPath, pcd.SavedCurrentlyExecutingCommandVarValue); Context.SetVariable(SpecialVariables.PSBoundParametersVarPath, pcd.SavedPSBoundParametersVarValue); this.Context.CurrentRunspace.UpdateRunspaceAvailability(pcd.RunspaceAvailability, true); } Dbg.Assert(_contextStack.Count == NestedPromptCount, "number of saved contexts should equal nesting count"); }
/// <summary> /// Internal proxy for EnterNestedPrompt. /// </summary> /// <param name="callingCommand"></param> internal void EnterNestedPrompt(InternalCommand callingCommand) { // Ensure we are in control of the pipeline LocalRunspace localRunspace = null; // This needs to be in a try / catch, since the LocalRunspace cast // tries to verify that the host supports interactive sessions. // Tests hosts do not. try { localRunspace = this.Runspace as LocalRunspace; } catch (PSNotImplementedException) { } if (localRunspace != null) { Pipeline currentlyRunningPipeline = this.Runspace.GetCurrentlyRunningPipeline(); if ((currentlyRunningPipeline != null) && (currentlyRunningPipeline == localRunspace.PulsePipeline)) { throw new InvalidOperationException(); } } // NTRAID#Windows OS Bugs-986407-2004/07/29 When kumarp has done the configuration work in the engine, it // should include setting a bit that indicates that the initialization is complete, and code should be // added here to throw an exception if this function is called before that bit is set. if (NestedPromptCount < 0) { Dbg.Assert(false, "nested prompt counter should never be negative."); throw PSTraceSource.NewInvalidOperationException( InternalHostStrings.EnterExitNestedPromptOutOfSync); } // Increment our nesting counter. When we set the value of the variable, we will replace any existing variable // of the same name. This is good, as any existing value is either 1) ours, and we have claim to replace it, or // 2) is a squatter, and we have claim to clobber it. ++NestedPromptCount; Context.SetVariable(SpecialVariables.NestedPromptCounterVarPath, NestedPromptCount); // On entering a subshell, save and reset values of certain bits of session state PromptContextData contextData = new PromptContextData(); contextData.SavedContextData = Context.SaveContextData(); contextData.SavedCurrentlyExecutingCommandVarValue = Context.GetVariableValue(SpecialVariables.CurrentlyExecutingCommandVarPath); contextData.SavedPSBoundParametersVarValue = Context.GetVariableValue(SpecialVariables.PSBoundParametersVarPath); contextData.RunspaceAvailability = this.Context.CurrentRunspace.RunspaceAvailability; contextData.LanguageMode = Context.LanguageMode; PSPropertyInfo commandInfoProperty = null; PSPropertyInfo stackTraceProperty = null; object oldCommandInfo = null; object oldStackTrace = null; if (callingCommand != null) { Dbg.Assert(callingCommand.Context == Context, "I expect that the contexts should match"); // Populate $CurrentlyExecutingCommand to facilitate debugging. One of the gotchas is that we are going to want // to expose more and more debug info. We could just populate more and more local variables but that is probably // a lousy approach as it pollutes the namespace. A better way to do it is to add NOTES to the variable value // object. PSObject newValue = PSObject.AsPSObject(callingCommand); commandInfoProperty = newValue.Properties["CommandInfo"]; if (commandInfoProperty == null) { newValue.Properties.Add(new PSNoteProperty("CommandInfo", callingCommand.CommandInfo)); } else { oldCommandInfo = commandInfoProperty.Value; commandInfoProperty.Value = callingCommand.CommandInfo; } stackTraceProperty = newValue.Properties["StackTrace"]; if (stackTraceProperty == null) { newValue.Properties.Add(new PSNoteProperty("StackTrace", new System.Diagnostics.StackTrace())); } else { oldStackTrace = stackTraceProperty.Value; stackTraceProperty.Value = new System.Diagnostics.StackTrace(); } Context.SetVariable(SpecialVariables.CurrentlyExecutingCommandVarPath, newValue); } _contextStack.Push(contextData); Dbg.Assert(_contextStack.Count == NestedPromptCount, "number of saved contexts should equal nesting count"); Context.PSDebugTraceStep = false; Context.PSDebugTraceLevel = 0; Context.ResetShellFunctionErrorOutputPipe(); // Lock down the language in the nested prompt if (Context.HasRunspaceEverUsedConstrainedLanguageMode) { Context.LanguageMode = PSLanguageMode.ConstrainedLanguage; } this.Context.CurrentRunspace.UpdateRunspaceAvailability(RunspaceAvailability.AvailableForNestedCommand, true); try { _externalHostRef.Value.EnterNestedPrompt(); } catch { // So where things really go south is this path; which is possible for hosts (like our ConsoleHost) // that don't return from EnterNestedPrompt immediately. // EnterNestedPrompt() starts // ExitNestedPrompt() called // EnterNestedPrompt throws ExitNestedPromptHelper(); throw; } finally { if (commandInfoProperty != null) { commandInfoProperty.Value = oldCommandInfo; } if (stackTraceProperty != null) { stackTraceProperty.Value = oldStackTrace; } } Dbg.Assert(NestedPromptCount >= 0, "nestedPromptCounter should be greater than or equal to 0"); }
/// <summary> /// Internal proxy for EnterNestedPrompt /// </summary> /// <param name="callingCommand"></param> /// internal void EnterNestedPrompt(InternalCommand callingCommand) { // Ensure we are in control of the pipeline LocalRunspace localRunspace = null; // This needs to be in a try / catch, since the LocalRunspace cast // tries to verify that the host supports interactive sessions. // Tests hosts do not. try { localRunspace = this.Runspace as LocalRunspace; } catch (PSNotImplementedException) { } if (localRunspace != null) { Pipeline currentlyRunningPipeline = this.Runspace.GetCurrentlyRunningPipeline(); if ((currentlyRunningPipeline != null) && (currentlyRunningPipeline == localRunspace.PulsePipeline)) throw new InvalidOperationException(); } // NTRAID#Windows OS Bugs-986407-2004/07/29 When kumarp has done the configuration work in the engine, it // should include setting a bit that indicates that the initialization is complete, and code should be // added here to throw an exception if this function is called before that bit is set. if (NestedPromptCount < 0) { Dbg.Assert(false, "nested prompt counter should never be negative."); throw PSTraceSource.NewInvalidOperationException( InternalHostStrings.EnterExitNestedPromptOutOfSync); } // Increment our nesting counter. When we set the value of the variable, we will replace any existing variable // of the same name. This is good, as any existing value is either 1) ours, and we have claim to replace it, or // 2) is a squatter, and we have claim to clobber it. ++NestedPromptCount; Context.SetVariable(SpecialVariables.NestedPromptCounterVarPath, NestedPromptCount); // On entering a subshell, save and reset values of certain bits of session state PromptContextData contextData = new PromptContextData(); contextData.SavedContextData = Context.SaveContextData(); contextData.SavedCurrentlyExecutingCommandVarValue = Context.GetVariableValue(SpecialVariables.CurrentlyExecutingCommandVarPath); contextData.SavedPSBoundParametersVarValue = Context.GetVariableValue(SpecialVariables.PSBoundParametersVarPath); contextData.RunspaceAvailability = this.Context.CurrentRunspace.RunspaceAvailability; contextData.LanguageMode = Context.LanguageMode; PSPropertyInfo commandInfoProperty = null; PSPropertyInfo stackTraceProperty = null; object oldCommandInfo = null; object oldStackTrace = null; if (callingCommand != null) { Dbg.Assert(callingCommand.Context == Context, "I expect that the contexts should match"); // Populate $CurrentlyExecutingCommand to facilitate debugging. One of the gotchas is that we are going to want // to expose more and more debug info. We could just populate more and more local variables but that is probably // a lousy approach as it pollutes the namespace. A better way to do it is to add NOTES to the variable value // object. PSObject newValue = PSObject.AsPSObject(callingCommand); commandInfoProperty = newValue.Properties["CommandInfo"]; if (commandInfoProperty == null) { newValue.Properties.Add(new PSNoteProperty("CommandInfo", callingCommand.CommandInfo)); } else { oldCommandInfo = commandInfoProperty.Value; commandInfoProperty.Value = callingCommand.CommandInfo; } #if !CORECLR //TODO:CORECLR StackTrace not in CoreCLR stackTraceProperty = newValue.Properties["StackTrace"]; if (stackTraceProperty == null) { newValue.Properties.Add(new PSNoteProperty("StackTrace", new System.Diagnostics.StackTrace())); } else { oldStackTrace = stackTraceProperty.Value; stackTraceProperty.Value = new System.Diagnostics.StackTrace(); } #endif Context.SetVariable(SpecialVariables.CurrentlyExecutingCommandVarPath, newValue); } _contextStack.Push(contextData); Dbg.Assert(_contextStack.Count == NestedPromptCount, "number of saved contexts should equal nesting count"); Context.PSDebugTraceStep = false; Context.PSDebugTraceLevel = 0; Context.ResetShellFunctionErrorOutputPipe(); // Lock down the language in the nested prompt if (Context.HasRunspaceEverUsedConstrainedLanguageMode) { Context.LanguageMode = PSLanguageMode.ConstrainedLanguage; } this.Context.CurrentRunspace.UpdateRunspaceAvailability(RunspaceAvailability.AvailableForNestedCommand, true); try { _externalHostRef.Value.EnterNestedPrompt(); } catch { // So where things really go south is this path; which is possible for hosts (like our ConsoleHost) // that don't return from EnterNestedPrompt immediately. // EnterNestedPrompt() starts // ExitNestedPrompt() called // EnterNestedPrompt throws ExitNestedPromptHelper(); throw; } finally { if (commandInfoProperty != null) { commandInfoProperty.Value = oldCommandInfo; } if (stackTraceProperty != null) { stackTraceProperty.Value = oldStackTrace; } } Dbg.Assert(NestedPromptCount >= 0, "nestedPromptCounter should be greater than or equal to 0"); }
internal void EnterNestedPrompt(InternalCommand callingCommand) { LocalRunspace runspace = null; try { runspace = this.Runspace as LocalRunspace; } catch (PSNotImplementedException) { } if (runspace != null) { Pipeline currentlyRunningPipeline = this.Runspace.GetCurrentlyRunningPipeline(); if ((currentlyRunningPipeline != null) && (currentlyRunningPipeline == runspace.PulsePipeline)) { throw new InvalidOperationException(); } } if (this.nestedPromptCount < 0) { throw PSTraceSource.NewInvalidOperationException("InternalHostStrings", "EnterExitNestedPromptOutOfSync", new object[0]); } this.nestedPromptCount++; this.executionContext.SetVariable(SpecialVariables.NestedPromptCounterVarPath, this.nestedPromptCount); PromptContextData item = new PromptContextData { SavedContextData = this.executionContext.SaveContextData(), SavedCurrentlyExecutingCommandVarValue = this.executionContext.GetVariableValue(SpecialVariables.CurrentlyExecutingCommandVarPath), SavedPSBoundParametersVarValue = this.executionContext.GetVariableValue(SpecialVariables.PSBoundParametersVarPath), RunspaceAvailability = this.Context.CurrentRunspace.RunspaceAvailability, LanguageMode = this.executionContext.LanguageMode }; PSPropertyInfo info = null; PSPropertyInfo info2 = null; object obj2 = null; object obj3 = null; if (callingCommand != null) { PSObject newValue = PSObject.AsPSObject(callingCommand); info = newValue.Properties["CommandInfo"]; if (info == null) { newValue.Properties.Add(new PSNoteProperty("CommandInfo", callingCommand.CommandInfo)); } else { obj2 = info.Value; info.Value = callingCommand.CommandInfo; } info2 = newValue.Properties["StackTrace"]; if (info2 == null) { newValue.Properties.Add(new PSNoteProperty("StackTrace", new StackTrace())); } else { obj3 = info2.Value; info2.Value = new StackTrace(); } this.executionContext.SetVariable(SpecialVariables.CurrentlyExecutingCommandVarPath, newValue); } this.contextStack.Push(item); this.executionContext.PSDebugTraceStep = false; this.executionContext.PSDebugTraceLevel = 0; this.executionContext.ResetShellFunctionErrorOutputPipe(); if (this.executionContext.HasRunspaceEverUsedConstrainedLanguageMode) { this.executionContext.LanguageMode = PSLanguageMode.ConstrainedLanguage; } this.Context.CurrentRunspace.UpdateRunspaceAvailability(RunspaceAvailability.AvailableForNestedCommand, true); try { this.externalHostRef.Value.EnterNestedPrompt(); } catch { this.ExitNestedPromptHelper(); throw; } finally { if (info != null) { info.Value = obj2; } if (info2 != null) { info2.Value = obj3; } } }