Skip to content

Commit 7eabf59

Browse files
authored
Merge pull request #348 from PowerShell/daviwil/fix-async-pssa
Fix PSScriptAnalyzer module loading in new async AnalysisService
2 parents 2c7709b + 710bd7d commit 7eabf59

File tree

2 files changed

+63
-38
lines changed

2 files changed

+63
-38
lines changed

src/PowerShellEditorServices/Analysis/AnalysisService.cs

Lines changed: 62 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class AnalysisService : IDisposable
2525
{
2626
#region Private Fields
2727

28+
private const int NumRunspaces = 2;
2829
private RunspacePool analysisRunspacePool;
2930
private PSModuleInfo scriptAnalyzerModuleInfo;
3031
private string[] activeRules;
@@ -103,18 +104,16 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
103104
this.SettingsPath = settingsPath;
104105
var sessionState = InitialSessionState.CreateDefault2();
105106

106-
// import PSScriptAnalyzer in all runspaces
107-
sessionState.ImportPSModule(new string[] { "PSScriptAnalyzer" });
108-
109107
// runspacepool takes care of queuing commands for us so we do not
110108
// need to worry about executing concurrent commands
111109
this.analysisRunspacePool = RunspaceFactory.CreateRunspacePool(sessionState);
112110

113111
// having more than one runspace doesn't block code formatting if one
114112
// runspace is occupied for diagnostics
115-
this.analysisRunspacePool.SetMaxRunspaces(2);
113+
this.analysisRunspacePool.SetMaxRunspaces(NumRunspaces);
116114
this.analysisRunspacePool.ThreadOptions = PSThreadOptions.ReuseThread;
117115
this.analysisRunspacePool.Open();
116+
118117
ActiveRules = IncludedRules.ToArray();
119118
InitializePSScriptAnalyzer();
120119
}
@@ -231,55 +230,75 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
231230

232231
private void FindPSScriptAnalyzer()
233232
{
234-
var modules = InvokePowerShell(
235-
"Get-Module",
236-
new Dictionary<string, object>
237-
{
238-
{ "ListAvailable", true },
239-
{ "Name", "PSScriptAnalyzer" }
240-
});
241-
var psModule = modules.Count() == 0 ? null : modules.FirstOrDefault();
242-
if (psModule != null)
233+
using (var ps = System.Management.Automation.PowerShell.Create())
243234
{
244-
scriptAnalyzerModuleInfo = psModule.ImmediateBaseObject as PSModuleInfo;
245-
Logger.Write(
246-
LogLevel.Normal,
247-
string.Format(
248-
"PSScriptAnalyzer found at {0}",
249-
scriptAnalyzerModuleInfo.Path));
250-
}
251-
else
252-
{
253-
Logger.Write(
254-
LogLevel.Normal,
255-
"PSScriptAnalyzer module was not found.");
235+
ps.RunspacePool = this.analysisRunspacePool;
236+
237+
ps.AddCommand("Get-Module")
238+
.AddParameter("ListAvailable")
239+
.AddParameter("Name", "PSScriptAnalyzer");
240+
241+
ps.AddCommand("Sort-Object")
242+
.AddParameter("Descending")
243+
.AddParameter("Property", "Version");
244+
245+
ps.AddCommand("Select-Object")
246+
.AddParameter("First", 1);
247+
248+
var modules = ps.Invoke();
249+
250+
var psModule = modules == null ? null : modules.FirstOrDefault();
251+
if (psModule != null)
252+
{
253+
scriptAnalyzerModuleInfo = psModule.ImmediateBaseObject as PSModuleInfo;
254+
Logger.Write(
255+
LogLevel.Normal,
256+
string.Format(
257+
"PSScriptAnalyzer found at {0}",
258+
scriptAnalyzerModuleInfo.Path));
259+
}
260+
else
261+
{
262+
Logger.Write(
263+
LogLevel.Normal,
264+
"PSScriptAnalyzer module was not found.");
265+
}
256266
}
257267
}
258268

259-
private void ImportPSScriptAnalyzer()
269+
private async Task<bool> ImportPSScriptAnalyzerAsync()
260270
{
261271
if (scriptAnalyzerModuleInfo != null)
262272
{
263-
var module = InvokePowerShell(
264-
"Import-Module",
265-
new Dictionary<string, object>
266-
{
267-
{ "ModuleInfo", scriptAnalyzerModuleInfo },
268-
{ "PassThru", true },
269-
});
273+
var module =
274+
await InvokePowerShellAsync(
275+
"Import-Module",
276+
new Dictionary<string, object>
277+
{
278+
{ "ModuleInfo", scriptAnalyzerModuleInfo },
279+
{ "PassThru", true },
280+
});
270281

271282
if (module.Count() == 0)
272283
{
273284
this.scriptAnalyzerModuleInfo = null;
274285
Logger.Write(LogLevel.Warning,
275286
String.Format("Cannot Import PSScriptAnalyzer: {0}"));
287+
288+
return false;
276289
}
277290
else
278291
{
279292
Logger.Write(LogLevel.Normal,
280-
String.Format("Successfully imported PSScriptAnalyzer"));
293+
String.Format(
294+
"Successfully imported PSScriptAnalyzer {0}",
295+
scriptAnalyzerModuleInfo.Version));
296+
297+
return true;
281298
}
282299
}
300+
301+
return false;
283302
}
284303

285304
private void EnumeratePSScriptAnalyzerRules()
@@ -302,10 +321,15 @@ private void InitializePSScriptAnalyzer()
302321
{
303322
FindPSScriptAnalyzer();
304323

305-
// this import is redundant if we are importing the
306-
// module while creating the runspace, but it helps
307-
// us log the import related messages.
308-
ImportPSScriptAnalyzer();
324+
List<Task> importTasks = new List<Task>();
325+
for (int i = 0; i < NumRunspaces; i++)
326+
{
327+
importTasks.Add(
328+
ImportPSScriptAnalyzerAsync());
329+
}
330+
331+
// Wait for the import requests to complete or fail
332+
Task.WaitAll(importTasks.ToArray());
309333

310334
EnumeratePSScriptAnalyzerRules();
311335
}

src/PowerShellEditorServices/Nano.PowerShellEditorServices.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@
202202
<Compile Include="..\PowerShellEditorServices.Protocol\LanguageServer\DocumentHighlight.cs" />
203203
<Compile Include="..\PowerShellEditorServices.Protocol\LanguageServer\ExpandAliasRequest.cs" />
204204
<Compile Include="..\PowerShellEditorServices.Protocol\LanguageServer\Hover.cs" />
205+
<Compile Include="..\PowerShellEditorServices.Protocol\LanguageServer\GetPSHostProcessesRequest.cs" />
205206
<Compile Include="..\PowerShellEditorServices.Protocol\Client\LanguageClientBase.cs" />
206207
<Compile Include="..\PowerShellEditorServices.Protocol\Server\LanguageServer.cs" />
207208
<Compile Include="..\PowerShellEditorServices.Protocol\Server\LanguageServerBase.cs" />

0 commit comments

Comments
 (0)