|
1 | 1 | // Copyright (c) Microsoft Corporation. |
2 | 2 | // Licensed under the MIT License. |
3 | 3 |
|
4 | | -using System.Linq; |
5 | | -using System.Threading.Tasks; |
6 | | -using Microsoft.Extensions.Logging; |
7 | | -using Microsoft.PowerShell.EditorServices.Logging; |
8 | | -using Microsoft.PowerShell.EditorServices.Services.DebugAdapter; |
9 | 4 | using System; |
10 | 5 | using System.Collections.Generic; |
11 | | -using System.Collections.ObjectModel; |
| 6 | +using System.Linq; |
12 | 7 | using System.Management.Automation; |
13 | 8 | using System.Threading; |
14 | | -using SMA = System.Management.Automation; |
15 | | -using Microsoft.PowerShell.EditorServices.Services.PowerShell.Utility; |
16 | | -using Microsoft.PowerShell.EditorServices.Services.PowerShell.Runspace; |
| 9 | +using System.Threading.Tasks; |
| 10 | +using Microsoft.Extensions.Logging; |
| 11 | +using Microsoft.PowerShell.EditorServices.Services.DebugAdapter; |
| 12 | +using Microsoft.PowerShell.EditorServices.Services.PowerShell.Execution; |
17 | 13 | using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host; |
| 14 | +using Microsoft.PowerShell.EditorServices.Services.PowerShell.Runspace; |
18 | 15 |
|
19 | 16 | namespace Microsoft.PowerShell.EditorServices.Services.PowerShell.Debugging |
20 | 17 | { |
21 | 18 | internal class DscBreakpointCapability |
22 | 19 | { |
| 20 | + private static bool? isDscInstalled; |
23 | 21 | private string[] dscResourceRootPaths = Array.Empty<string>(); |
24 | | - |
25 | 22 | private readonly Dictionary<string, int[]> breakpointsPerFile = new(); |
26 | 23 |
|
27 | 24 | public async Task<IEnumerable<BreakpointDetails>> SetLineBreakpointsAsync( |
@@ -79,88 +76,57 @@ public bool IsDscResourcePath(string scriptPath) |
79 | 76 | StringComparison.CurrentCultureIgnoreCase)); |
80 | 77 | } |
81 | 78 |
|
82 | | - public static Task<DscBreakpointCapability> GetDscCapabilityAsync( |
| 79 | + public static async Task<DscBreakpointCapability> GetDscCapabilityAsync( |
83 | 80 | ILogger logger, |
84 | 81 | IRunspaceInfo currentRunspace, |
85 | | - PsesInternalHost psesHost, |
86 | | - CancellationToken cancellationToken) |
| 82 | + PsesInternalHost psesHost) |
87 | 83 | { |
88 | 84 | // DSC support is enabled only for Windows PowerShell. |
89 | 85 | if ((currentRunspace.PowerShellVersionDetails.Version.Major >= 6) && |
90 | 86 | (currentRunspace.RunspaceOrigin != RunspaceOrigin.DebuggedRunspace)) |
91 | 87 | { |
92 | | - return Task.FromResult<DscBreakpointCapability>(null); |
| 88 | + return null; |
93 | 89 | } |
94 | 90 |
|
95 | | - DscBreakpointCapability getDscBreakpointCapabilityFunc(SMA.PowerShell pwsh, CancellationToken _) |
| 91 | + if (!isDscInstalled.HasValue) |
96 | 92 | { |
97 | | - PSInvocationSettings invocationSettings = new() |
98 | | - { |
99 | | - AddToHistory = false, |
100 | | - ErrorActionPreference = ActionPreference.Stop |
101 | | - }; |
102 | | - |
103 | | - PSModuleInfo dscModule = null; |
104 | | - try |
105 | | - { |
106 | | - dscModule = pwsh.AddCommand("Import-Module") |
107 | | - .AddArgument(@"C:\Program Files\DesiredStateConfiguration\1.0.0.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psd1") |
108 | | - .AddParameter("PassThru") |
109 | | - .InvokeAndClear<PSModuleInfo>(invocationSettings) |
110 | | - .FirstOrDefault(); |
111 | | - } |
112 | | - catch (RuntimeException e) |
113 | | - { |
114 | | - logger.LogException("Could not load the DSC module!", e); |
115 | | - } |
116 | | - |
117 | | - if (dscModule == null) |
118 | | - { |
119 | | - logger.LogTrace("Side-by-side DSC module was not found."); |
120 | | - return null; |
121 | | - } |
122 | | - |
123 | | - logger.LogTrace("Side-by-side DSC module found, gathering DSC resource paths..."); |
124 | | - |
125 | | - // The module was loaded, add the breakpoint capability |
126 | | - DscBreakpointCapability capability = new(); |
127 | | - |
128 | | - pwsh.AddCommand("Microsoft.PowerShell.Utility\\Write-Host") |
129 | | - .AddArgument("Gathering DSC resource paths, this may take a while...") |
130 | | - .InvokeAndClear(invocationSettings); |
131 | | - |
132 | | - Collection<string> resourcePaths = null; |
133 | | - try |
134 | | - { |
135 | | - // Get the list of DSC resource paths |
136 | | - resourcePaths = pwsh.AddCommand("Get-DscResource") |
137 | | - .AddCommand("Select-Object") |
138 | | - .AddParameter("ExpandProperty", "ParentPath") |
139 | | - .InvokeAndClear<string>(invocationSettings); |
140 | | - } |
141 | | - catch (CmdletInvocationException e) |
142 | | - { |
143 | | - logger.LogException("Get-DscResource failed!", e); |
144 | | - } |
145 | | - |
146 | | - if (resourcePaths == null) |
147 | | - { |
148 | | - logger.LogTrace("No DSC resources found."); |
149 | | - return null; |
150 | | - } |
| 93 | + PSCommand psCommand = new PSCommand() |
| 94 | + .AddCommand("Import-Module") |
| 95 | + .AddArgument(@"C:\Program Files\DesiredStateConfiguration\1.0.0.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psd1") |
| 96 | + .AddParameter("PassThru"); |
| 97 | + |
| 98 | + IReadOnlyList<PSModuleInfo> dscModule = |
| 99 | + await psesHost.ExecutePSCommandAsync<PSModuleInfo>( |
| 100 | + psCommand, |
| 101 | + CancellationToken.None, |
| 102 | + new PowerShellExecutionOptions { ThrowOnError = false }).ConfigureAwait(false); |
| 103 | + |
| 104 | + isDscInstalled = dscModule.Count > 0; |
| 105 | + logger.LogTrace("Side-by-side DSC module found: " + isDscInstalled.Value); |
| 106 | + } |
151 | 107 |
|
152 | | - capability.dscResourceRootPaths = resourcePaths.ToArray(); |
| 108 | + if (isDscInstalled.Value) |
| 109 | + { |
| 110 | + PSCommand psCommand = new PSCommand() |
| 111 | + .AddCommand("Get-DscResource") |
| 112 | + .AddCommand("Select-Object") |
| 113 | + .AddParameter("ExpandProperty", "ParentPath"); |
| 114 | + |
| 115 | + IReadOnlyList<string> resourcePaths = |
| 116 | + await psesHost.ExecutePSCommandAsync<string>( |
| 117 | + psCommand, |
| 118 | + CancellationToken.None, |
| 119 | + new PowerShellExecutionOptions { ThrowOnError = false } |
| 120 | + ).ConfigureAwait(false); |
153 | 121 |
|
154 | 122 | logger.LogTrace($"DSC resources found: {resourcePaths.Count}"); |
155 | | - |
156 | | - return capability; |
| 123 | + return new DscBreakpointCapability |
| 124 | + { |
| 125 | + dscResourceRootPaths = resourcePaths.ToArray() |
| 126 | + }; |
157 | 127 | } |
158 | 128 |
|
159 | | - return psesHost.ExecuteDelegateAsync( |
160 | | - nameof(getDscBreakpointCapabilityFunc), |
161 | | - executionOptions: null, |
162 | | - getDscBreakpointCapabilityFunc, |
163 | | - cancellationToken); |
| 129 | + return null; |
164 | 130 | } |
165 | 131 | } |
166 | 132 | } |
0 commit comments