-
Notifications
You must be signed in to change notification settings - Fork 237
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 | |
} |