-
Notifications
You must be signed in to change notification settings - Fork 240
Closed
Labels
Description
Lines 90 to 166 in 9e1a17a
| // DSC support is enabled only for Windows PowerShell. | |
| if ((runspaceDetails.PowerShellVersion.Version.Major < 6) && | |
| (runspaceDetails.Context != RunspaceContext.DebuggedRunspace)) | |
| { | |
| using (PowerShell powerShell = PowerShell.Create()) | |
| { | |
| powerShell.Runspace = runspaceDetails.Runspace; | |
| // Attempt to import the updated DSC module | |
| powerShell.AddCommand("Import-Module"); | |
| powerShell.AddArgument(@"C:\Program Files\DesiredStateConfiguration\1.0.0.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psd1"); | |
| powerShell.AddParameter("PassThru"); | |
| powerShell.AddParameter("ErrorAction", "Ignore"); | |
| PSObject moduleInfo = null; | |
| try | |
| { | |
| moduleInfo = powerShell.Invoke().FirstOrDefault(); | |
| } | |
| catch (RuntimeException e) | |
| { | |
| logger.LogException("Could not load the DSC module!", e); | |
| } | |
| if (moduleInfo != null) | |
| { | |
| logger.LogTrace("Side-by-side DSC module found, gathering DSC resource paths..."); | |
| // The module was loaded, add the breakpoint capability | |
| capability = new DscBreakpointCapability(); | |
| runspaceDetails.AddCapability(capability); | |
| powerShell.Commands.Clear(); | |
| powerShell | |
| .AddCommand("Microsoft.PowerShell.Utility\\Write-Host") | |
| .AddArgument("Gathering DSC resource paths, this may take a while...") | |
| .Invoke(); | |
| // Get the list of DSC resource paths | |
| powerShell.Commands.Clear(); | |
| powerShell | |
| .AddCommand("Get-DscResource") | |
| .AddCommand("Select-Object") | |
| .AddParameter("ExpandProperty", "ParentPath"); | |
| Collection<PSObject> resourcePaths = null; | |
| try | |
| { | |
| resourcePaths = powerShell.Invoke(); | |
| } | |
| catch (CmdletInvocationException e) | |
| { | |
| logger.LogException("Get-DscResource failed!", e); | |
| } | |
| if (resourcePaths != null) | |
| { | |
| capability.dscResourceRootPaths = | |
| resourcePaths | |
| .Select(o => (string)o.BaseObject) | |
| .ToArray(); | |
| logger.LogTrace($"DSC resources found: {resourcePaths.Count}"); | |
| } | |
| else | |
| { | |
| logger.LogTrace($"No DSC resources found."); | |
| } | |
| } | |
| else | |
| { | |
| logger.LogTrace($"Side-by-side DSC module was not found."); | |
| } | |
| } | |
| } |
Lines 92 to 114 in 1ffe6db
| if (_debugStateService.WaitingForAttach && | |
| e.ChangeAction == RunspaceChangeAction.Enter && | |
| e.NewRunspace.Context == RunspaceContext.DebuggedRunspace) | |
| { | |
| // Sends the InitializedEvent so that the debugger will continue | |
| // sending configuration requests | |
| _debugStateService.WaitingForAttach = false; | |
| _debugStateService.ServerStarted.SetResult(true); | |
| } | |
| else if ( | |
| e.ChangeAction == RunspaceChangeAction.Exit && | |
| _powerShellContextService.IsDebuggerStopped) | |
| { | |
| // Exited the session while the debugger is stopped, | |
| // send a ContinuedEvent so that the client changes the | |
| // UI to appear to be running again | |
| _debugAdapterServer.SendNotification(EventNames.Continued, | |
| new ContinuedEvent | |
| { | |
| ThreadId = 1, | |
| AllThreadsContinued = true | |
| }); | |
| } |
Lines 2496 to 2512 in 29e44b6
| // Pop the current RunspaceDetails if we were attached | |
| // to a runspace and the resume action is Stop | |
| if (this.CurrentRunspace.Context == RunspaceContext.DebuggedRunspace && | |
| e.ResumeAction == DebuggerResumeAction.Stop) | |
| { | |
| this.PopRunspace(); | |
| } | |
| else if (e.ResumeAction != DebuggerResumeAction.Stop) | |
| { | |
| // Update the session state | |
| this.OnSessionStateChanged( | |
| this, | |
| new SessionStateChangedEventArgs( | |
| PowerShellContextState.Running, | |
| PowerShellExecutionResult.NotFinished, | |
| null)); | |
| } |
Lines 1514 to 1517 in 29e44b6
| case RunspaceContext.DebuggedRunspace: | |
| // An attached runspace will be detached when the | |
| // running pipeline is aborted | |
| break; |
Lines 631 to 634 in 9e1a17a
| if (runspaceDetails.Context == RunspaceContext.DebuggedRunspace) | |
| { | |
| this.powerShellContext.ExecuteCommandAsync(createCommand).Wait(); | |
| } |
See also:
Lines 15 to 322 in 9e1a17a
| /// <summary> | |
| /// Specifies the possible types of a runspace. | |
| /// </summary> | |
| internal enum RunspaceLocation | |
| { | |
| /// <summary> | |
| /// A runspace on the local machine. | |
| /// </summary> | |
| Local, | |
| /// <summary> | |
| /// A runspace on a different machine. | |
| /// </summary> | |
| Remote | |
| } | |
| /// <summary> | |
| /// Specifies the context in which the runspace was encountered. | |
| /// </summary> | |
| internal enum RunspaceContext | |
| { | |
| /// <summary> | |
| /// The original runspace in a local or remote session. | |
| /// </summary> | |
| Original, | |
| /// <summary> | |
| /// A runspace in a process that was entered with Enter-PSHostProcess. | |
| /// </summary> | |
| EnteredProcess, | |
| /// <summary> | |
| /// A runspace that is being debugged with Debug-Runspace. | |
| /// </summary> | |
| DebuggedRunspace | |
| } | |
| /// <summary> | |
| /// Provides details about a runspace being used in the current | |
| /// editing session. | |
| /// </summary> | |
| internal class RunspaceDetails | |
| { | |
| #region Private Fields | |
| private Dictionary<Type, IRunspaceCapability> capabilities = | |
| new Dictionary<Type, IRunspaceCapability>(); | |
| #endregion | |
| #region Properties | |
| /// <summary> | |
| /// Gets the Runspace instance for which this class contains details. | |
| /// </summary> | |
| internal Runspace Runspace { get; private set; } | |
| /// <summary> | |
| /// Gets the PowerShell version of the new runspace. | |
| /// </summary> | |
| public PowerShellVersionDetails PowerShellVersion { get; private set; } | |
| /// <summary> | |
| /// Gets the runspace location, either Local or Remote. | |
| /// </summary> | |
| public RunspaceLocation Location { get; private set; } | |
| /// <summary> | |
| /// Gets the context in which the runspace was encountered. | |
| /// </summary> | |
| public RunspaceContext Context { get; private set; } | |
| /// <summary> | |
| /// Gets the "connection string" for the runspace, generally the | |
| /// ComputerName for a remote runspace or the ProcessId of an | |
| /// "Attach" runspace. | |
| /// </summary> | |
| public string ConnectionString { get; private set; } | |
| /// <summary> | |
| /// Gets the details of the runspace's session at the time this | |
| /// RunspaceDetails object was created. | |
| /// </summary> | |
| public SessionDetails SessionDetails { get; private set; } | |
| #endregion | |
| #region Constructors | |
| /// <summary> | |
| /// Creates a new instance of the RunspaceDetails class. | |
| /// </summary> | |
| /// <param name="runspace"> | |
| /// The runspace for which this instance contains details. | |
| /// </param> | |
| /// <param name="sessionDetails"> | |
| /// The SessionDetails for the runspace. | |
| /// </param> | |
| /// <param name="powerShellVersion"> | |
| /// The PowerShellVersionDetails of the runspace. | |
| /// </param> | |
| /// <param name="runspaceLocation"> | |
| /// The RunspaceLocation of the runspace. | |
| /// </param> | |
| /// <param name="runspaceContext"> | |
| /// The RunspaceContext of the runspace. | |
| /// </param> | |
| /// <param name="connectionString"> | |
| /// The connection string of the runspace. | |
| /// </param> | |
| public RunspaceDetails( | |
| Runspace runspace, | |
| SessionDetails sessionDetails, | |
| PowerShellVersionDetails powerShellVersion, | |
| RunspaceLocation runspaceLocation, | |
| RunspaceContext runspaceContext, | |
| string connectionString) | |
| { | |
| this.Runspace = runspace; | |
| this.SessionDetails = sessionDetails; | |
| this.PowerShellVersion = powerShellVersion; | |
| this.Location = runspaceLocation; | |
| this.Context = runspaceContext; | |
| this.ConnectionString = connectionString; | |
| } | |
| #endregion | |
| #region Public Methods | |
| internal void AddCapability<TCapability>(TCapability capability) | |
| where TCapability : IRunspaceCapability | |
| { | |
| this.capabilities.Add(typeof(TCapability), capability); | |
| } | |
| internal TCapability GetCapability<TCapability>() | |
| where TCapability : IRunspaceCapability | |
| { | |
| TCapability capability = default(TCapability); | |
| this.TryGetCapability<TCapability>(out capability); | |
| return capability; | |
| } | |
| internal bool TryGetCapability<TCapability>(out TCapability capability) | |
| where TCapability : IRunspaceCapability | |
| { | |
| IRunspaceCapability capabilityAsInterface = default(TCapability); | |
| if (this.capabilities.TryGetValue(typeof(TCapability), out capabilityAsInterface)) | |
| { | |
| capability = (TCapability)capabilityAsInterface; | |
| return true; | |
| } | |
| capability = default(TCapability); | |
| return false; | |
| } | |
| internal bool HasCapability<TCapability>() | |
| { | |
| return this.capabilities.ContainsKey(typeof(TCapability)); | |
| } | |
| /// <summary> | |
| /// Creates and populates a new RunspaceDetails instance for the given runspace. | |
| /// </summary> | |
| /// <param name="runspace"> | |
| /// The runspace for which details will be gathered. | |
| /// </param> | |
| /// <param name="sessionDetails"> | |
| /// The SessionDetails for the runspace. | |
| /// </param> | |
| /// <param name="logger">An ILogger implementation used for writing log messages.</param> | |
| /// <returns>A new RunspaceDetails instance.</returns> | |
| internal static RunspaceDetails CreateFromRunspace( | |
| Runspace runspace, | |
| SessionDetails sessionDetails, | |
| ILogger logger) | |
| { | |
| Validate.IsNotNull(nameof(runspace), runspace); | |
| Validate.IsNotNull(nameof(sessionDetails), sessionDetails); | |
| var runspaceLocation = RunspaceLocation.Local; | |
| var runspaceContext = RunspaceContext.Original; | |
| var versionDetails = PowerShellVersionDetails.GetVersionDetails(runspace, logger); | |
| string connectionString = null; | |
| if (runspace.ConnectionInfo != null) | |
| { | |
| // Use 'dynamic' to avoid missing NamedPipeRunspaceConnectionInfo | |
| // on PS v3 and v4 | |
| try | |
| { | |
| dynamic connectionInfo = runspace.ConnectionInfo; | |
| if (connectionInfo.ProcessId != null) | |
| { | |
| connectionString = connectionInfo.ProcessId.ToString(); | |
| runspaceContext = RunspaceContext.EnteredProcess; | |
| } | |
| } | |
| catch (RuntimeBinderException) | |
| { | |
| // ProcessId property isn't on the object, move on. | |
| } | |
| // Grab the $host.name which will tell us if we're in a PSRP session or not | |
| string hostName = | |
| PowerShellContextService.ExecuteScriptAndGetItem<string>( | |
| "$Host.Name", | |
| runspace, | |
| defaultValue: string.Empty, | |
| useLocalScope: true); | |
| // hostname is 'ServerRemoteHost' when the user enters a session. | |
| // ex. Enter-PSSession | |
| // Attaching to process currently needs to be marked as a local session | |
| // so we skip this if block if the runspace is from Enter-PSHostProcess | |
| if (hostName.Equals("ServerRemoteHost", StringComparison.Ordinal) | |
| && runspace.OriginalConnectionInfo?.GetType().ToString() != "System.Management.Automation.Runspaces.NamedPipeConnectionInfo") | |
| { | |
| runspaceLocation = RunspaceLocation.Remote; | |
| connectionString = | |
| runspace.ConnectionInfo.ComputerName + | |
| (connectionString != null ? $"-{connectionString}" : string.Empty); | |
| } | |
| } | |
| return | |
| new RunspaceDetails( | |
| runspace, | |
| sessionDetails, | |
| versionDetails, | |
| runspaceLocation, | |
| runspaceContext, | |
| connectionString); | |
| } | |
| /// <summary> | |
| /// Creates a clone of the given runspace through which another | |
| /// runspace was attached. Sets the IsAttached property of the | |
| /// resulting RunspaceDetails object to true. | |
| /// </summary> | |
| /// <param name="runspaceDetails"> | |
| /// The RunspaceDetails object which the new object based. | |
| /// </param> | |
| /// <param name="runspaceContext"> | |
| /// The RunspaceContext of the runspace. | |
| /// </param> | |
| /// <param name="sessionDetails"> | |
| /// The SessionDetails for the runspace. | |
| /// </param> | |
| /// <returns> | |
| /// A new RunspaceDetails instance for the attached runspace. | |
| /// </returns> | |
| public static RunspaceDetails CreateFromContext( | |
| RunspaceDetails runspaceDetails, | |
| RunspaceContext runspaceContext, | |
| SessionDetails sessionDetails) | |
| { | |
| return | |
| new RunspaceDetails( | |
| runspaceDetails.Runspace, | |
| sessionDetails, | |
| runspaceDetails.PowerShellVersion, | |
| runspaceDetails.Location, | |
| runspaceContext, | |
| runspaceDetails.ConnectionString); | |
| } | |
| /// <summary> | |
| /// Creates a new RunspaceDetails object from a remote | |
| /// debugging session. | |
| /// </summary> | |
| /// <param name="runspaceDetails"> | |
| /// The RunspaceDetails object which the new object based. | |
| /// </param> | |
| /// <param name="runspaceLocation"> | |
| /// The RunspaceLocation of the runspace. | |
| /// </param> | |
| /// <param name="runspaceContext"> | |
| /// The RunspaceContext of the runspace. | |
| /// </param> | |
| /// <param name="sessionDetails"> | |
| /// The SessionDetails for the runspace. | |
| /// </param> | |
| /// <returns> | |
| /// A new RunspaceDetails instance for the attached runspace. | |
| /// </returns> | |
| public static RunspaceDetails CreateFromDebugger( | |
| RunspaceDetails runspaceDetails, | |
| RunspaceLocation runspaceLocation, | |
| RunspaceContext runspaceContext, | |
| SessionDetails sessionDetails) | |
| { | |
| // TODO: Get the PowerShellVersion correctly! | |
| return | |
| new RunspaceDetails( | |
| runspaceDetails.Runspace, | |
| sessionDetails, | |
| runspaceDetails.PowerShellVersion, | |
| runspaceLocation, | |
| runspaceContext, | |
| runspaceDetails.ConnectionString); | |
| } | |
| #endregion | |
| } |