77using System ;
88using System . Linq ;
99using System . Management . Automation . Runspaces ;
10- using System . Threading ;
1110using System . Threading . Tasks ;
1211using Microsoft . PowerShell . EditorServices . Console ;
1312using System . Management . Automation ;
@@ -28,6 +27,15 @@ public class AnalysisService : IDisposable
2827 private const int NumRunspaces = 2 ;
2928 private RunspacePool analysisRunspacePool ;
3029 private PSModuleInfo scriptAnalyzerModuleInfo ;
30+
31+ private bool hasScriptAnalyzerModule
32+ {
33+ get
34+ {
35+ return scriptAnalyzerModuleInfo != null ;
36+ }
37+ }
38+
3139 private string [ ] activeRules ;
3240 private string settingsPath ;
3341
@@ -102,7 +110,10 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
102110 try
103111 {
104112 this . SettingsPath = settingsPath ;
113+
114+ scriptAnalyzerModuleInfo = FindPSScriptAnalyzerModule ( ) ;
105115 var sessionState = InitialSessionState . CreateDefault2 ( ) ;
116+ sessionState . ImportPSModulesFromPath ( scriptAnalyzerModuleInfo . ModuleBase ) ;
106117
107118 // runspacepool takes care of queuing commands for us so we do not
108119 // need to worry about executing concurrent commands
@@ -115,7 +126,7 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
115126 this . analysisRunspacePool . Open ( ) ;
116127
117128 ActiveRules = IncludedRules . ToArray ( ) ;
118- InitializePSScriptAnalyzer ( ) ;
129+ EnumeratePSScriptAnalyzerRules ( ) ;
119130 }
120131 catch ( Exception e )
121132 {
@@ -158,7 +169,7 @@ public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(ScriptFile file, H
158169 public IEnumerable < string > GetPSScriptAnalyzerRules ( )
159170 {
160171 List < string > ruleNames = new List < string > ( ) ;
161- if ( scriptAnalyzerModuleInfo != null )
172+ if ( hasScriptAnalyzerModule )
162173 {
163174 var ruleObjects = InvokePowerShell ( "Get-ScriptAnalyzerRule" , new Dictionary < string , object > ( ) ) ;
164175 foreach ( var rule in ruleObjects )
@@ -213,7 +224,7 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
213224 string [ ] rules ,
214225 TSettings settings ) where TSettings : class
215226 {
216- if ( this . scriptAnalyzerModuleInfo != null
227+ if ( hasScriptAnalyzerModule
217228 && file . IsAnalysisEnabled
218229 && ( typeof ( TSettings ) == typeof ( string ) || typeof ( TSettings ) == typeof ( Hashtable ) )
219230 && ( rules != null || settings != null ) )
@@ -228,12 +239,10 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
228239 }
229240 }
230241
231- private void FindPSScriptAnalyzer ( )
242+ private static PSModuleInfo FindPSScriptAnalyzerModule ( )
232243 {
233244 using ( var ps = System . Management . Automation . PowerShell . Create ( ) )
234245 {
235- ps . RunspacePool = this . analysisRunspacePool ;
236-
237246 ps . AddCommand ( "Get-Module" )
238247 . AddParameter ( "ListAvailable" )
239248 . AddParameter ( "Name" , "PSScriptAnalyzer" ) ;
@@ -245,65 +254,29 @@ private void FindPSScriptAnalyzer()
245254 ps . AddCommand ( "Select-Object" )
246255 . AddParameter ( "First" , 1 ) ;
247256
248- var modules = ps . Invoke ( ) ;
249-
250- var psModule = modules == null ? null : modules . FirstOrDefault ( ) ;
251- if ( psModule != null )
257+ var modules = ps . Invoke < PSModuleInfo > ( ) ;
258+ var psModuleInfo = modules == null ? null : modules . FirstOrDefault ( ) ;
259+ if ( psModuleInfo != null )
252260 {
253- scriptAnalyzerModuleInfo = psModule . ImmediateBaseObject as PSModuleInfo ;
254261 Logger . Write (
255262 LogLevel . Normal ,
256263 string . Format (
257264 "PSScriptAnalyzer found at {0}" ,
258- scriptAnalyzerModuleInfo . Path ) ) ;
259- }
260- else
261- {
262- Logger . Write (
263- LogLevel . Normal ,
264- "PSScriptAnalyzer module was not found." ) ;
265- }
266- }
267- }
268-
269- private async Task < bool > ImportPSScriptAnalyzerAsync ( )
270- {
271- if ( scriptAnalyzerModuleInfo != null )
272- {
273- var module =
274- await InvokePowerShellAsync (
275- "Import-Module" ,
276- new Dictionary < string , object >
277- {
278- { "ModuleInfo" , scriptAnalyzerModuleInfo } ,
279- { "PassThru" , true } ,
280- } ) ;
281-
282- if ( module . Count ( ) == 0 )
283- {
284- this . scriptAnalyzerModuleInfo = null ;
285- Logger . Write ( LogLevel . Warning ,
286- String . Format ( "Cannot Import PSScriptAnalyzer: {0}" ) ) ;
265+ psModuleInfo . Path ) ) ;
287266
288- return false ;
267+ return psModuleInfo ;
289268 }
290- else
291- {
292- Logger . Write ( LogLevel . Normal ,
293- String . Format (
294- "Successfully imported PSScriptAnalyzer {0}" ,
295- scriptAnalyzerModuleInfo . Version ) ) ;
296269
297- return true ;
298- }
270+ Logger . Write (
271+ LogLevel . Normal ,
272+ "PSScriptAnalyzer module was not found." ) ;
273+ return null ;
299274 }
300-
301- return false ;
302275 }
303276
304277 private void EnumeratePSScriptAnalyzerRules ( )
305278 {
306- if ( scriptAnalyzerModuleInfo != null )
279+ if ( hasScriptAnalyzerModule )
307280 {
308281 var rules = GetPSScriptAnalyzerRules ( ) ;
309282 var sb = new StringBuilder ( ) ;
@@ -317,31 +290,14 @@ private void EnumeratePSScriptAnalyzerRules()
317290 }
318291 }
319292
320- private void InitializePSScriptAnalyzer ( )
321- {
322- FindPSScriptAnalyzer ( ) ;
323-
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 ( ) ) ;
333-
334- EnumeratePSScriptAnalyzerRules ( ) ;
335- }
336-
337- private async Task < IEnumerable < PSObject > > GetDiagnosticRecordsAsync < TSettings > (
293+ private async Task < PSObject [ ] > GetDiagnosticRecordsAsync < TSettings > (
338294 ScriptFile file ,
339295 string [ ] rules ,
340296 TSettings settings ) where TSettings : class
341297 {
342- IEnumerable < PSObject > diagnosticRecords = Enumerable . Empty < PSObject > ( ) ;
298+ var diagnosticRecords = new PSObject [ 0 ] ;
343299
344- if ( this . scriptAnalyzerModuleInfo != null
300+ if ( hasScriptAnalyzerModule
345301 && ( typeof ( TSettings ) == typeof ( string )
346302 || typeof ( TSettings ) == typeof ( Hashtable ) ) )
347303 {
@@ -375,14 +331,14 @@ private async Task<IEnumerable<PSObject>> GetDiagnosticRecordsAsync<TSettings>(
375331 return diagnosticRecords ;
376332 }
377333
378- private IEnumerable < PSObject > InvokePowerShell ( string command , IDictionary < string , object > paramArgMap )
334+ private PSObject [ ] InvokePowerShell ( string command , IDictionary < string , object > paramArgMap )
379335 {
380336 var task = InvokePowerShellAsync ( command , paramArgMap ) ;
381337 task . Wait ( ) ;
382338 return task . Result ;
383339 }
384340
385- private async Task < IEnumerable < PSObject > > InvokePowerShellAsync ( string command , IDictionary < string , object > paramArgMap )
341+ private async Task < PSObject [ ] > InvokePowerShellAsync ( string command , IDictionary < string , object > paramArgMap )
386342 {
387343 using ( var powerShell = System . Management . Automation . PowerShell . Create ( ) )
388344 {
@@ -396,10 +352,10 @@ private async Task<IEnumerable<PSObject>> InvokePowerShellAsync(string command,
396352 var result = await Task . Factory . FromAsync ( powerShell . BeginInvoke ( ) , powerShell . EndInvoke ) ;
397353 if ( result == null )
398354 {
399- return Enumerable . Empty < PSObject > ( ) ;
355+ return new PSObject [ 0 ] ;
400356 }
401357
402- return result ;
358+ return result . ToArray ( ) ; ;
403359 }
404360 }
405361
0 commit comments