7
7
using System ;
8
8
using System . Linq ;
9
9
using System . Management . Automation . Runspaces ;
10
- using System . Threading ;
11
10
using System . Threading . Tasks ;
12
11
using Microsoft . PowerShell . EditorServices . Console ;
13
12
using System . Management . Automation ;
@@ -28,6 +27,15 @@ public class AnalysisService : IDisposable
28
27
private const int NumRunspaces = 2 ;
29
28
private RunspacePool analysisRunspacePool ;
30
29
private PSModuleInfo scriptAnalyzerModuleInfo ;
30
+
31
+ private bool hasScriptAnalyzerModule
32
+ {
33
+ get
34
+ {
35
+ return scriptAnalyzerModuleInfo != null ;
36
+ }
37
+ }
38
+
31
39
private string [ ] activeRules ;
32
40
private string settingsPath ;
33
41
@@ -102,7 +110,10 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
102
110
try
103
111
{
104
112
this . SettingsPath = settingsPath ;
113
+
114
+ scriptAnalyzerModuleInfo = FindPSScriptAnalyzerModule ( ) ;
105
115
var sessionState = InitialSessionState . CreateDefault2 ( ) ;
116
+ sessionState . ImportPSModulesFromPath ( scriptAnalyzerModuleInfo . ModuleBase ) ;
106
117
107
118
// runspacepool takes care of queuing commands for us so we do not
108
119
// need to worry about executing concurrent commands
@@ -115,7 +126,7 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
115
126
this . analysisRunspacePool . Open ( ) ;
116
127
117
128
ActiveRules = IncludedRules . ToArray ( ) ;
118
- InitializePSScriptAnalyzer ( ) ;
129
+ EnumeratePSScriptAnalyzerRules ( ) ;
119
130
}
120
131
catch ( Exception e )
121
132
{
@@ -158,7 +169,7 @@ public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(ScriptFile file, H
158
169
public IEnumerable < string > GetPSScriptAnalyzerRules ( )
159
170
{
160
171
List < string > ruleNames = new List < string > ( ) ;
161
- if ( scriptAnalyzerModuleInfo != null )
172
+ if ( hasScriptAnalyzerModule )
162
173
{
163
174
var ruleObjects = InvokePowerShell ( "Get-ScriptAnalyzerRule" , new Dictionary < string , object > ( ) ) ;
164
175
foreach ( var rule in ruleObjects )
@@ -213,7 +224,7 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
213
224
string [ ] rules ,
214
225
TSettings settings ) where TSettings : class
215
226
{
216
- if ( this . scriptAnalyzerModuleInfo != null
227
+ if ( hasScriptAnalyzerModule
217
228
&& file . IsAnalysisEnabled
218
229
&& ( typeof ( TSettings ) == typeof ( string ) || typeof ( TSettings ) == typeof ( Hashtable ) )
219
230
&& ( rules != null || settings != null ) )
@@ -228,12 +239,10 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
228
239
}
229
240
}
230
241
231
- private void FindPSScriptAnalyzer ( )
242
+ private static PSModuleInfo FindPSScriptAnalyzerModule ( )
232
243
{
233
244
using ( var ps = System . Management . Automation . PowerShell . Create ( ) )
234
245
{
235
- ps . RunspacePool = this . analysisRunspacePool ;
236
-
237
246
ps . AddCommand ( "Get-Module" )
238
247
. AddParameter ( "ListAvailable" )
239
248
. AddParameter ( "Name" , "PSScriptAnalyzer" ) ;
@@ -245,65 +254,29 @@ private void FindPSScriptAnalyzer()
245
254
ps . AddCommand ( "Select-Object" )
246
255
. AddParameter ( "First" , 1 ) ;
247
256
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 )
252
260
{
253
- scriptAnalyzerModuleInfo = psModule . ImmediateBaseObject as PSModuleInfo ;
254
261
Logger . Write (
255
262
LogLevel . Normal ,
256
263
string . Format (
257
264
"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 ) ) ;
287
266
288
- return false ;
267
+ return psModuleInfo ;
289
268
}
290
- else
291
- {
292
- Logger . Write ( LogLevel . Normal ,
293
- String . Format (
294
- "Successfully imported PSScriptAnalyzer {0}" ,
295
- scriptAnalyzerModuleInfo . Version ) ) ;
296
269
297
- return true ;
298
- }
270
+ Logger . Write (
271
+ LogLevel . Normal ,
272
+ "PSScriptAnalyzer module was not found." ) ;
273
+ return null ;
299
274
}
300
-
301
- return false ;
302
275
}
303
276
304
277
private void EnumeratePSScriptAnalyzerRules ( )
305
278
{
306
- if ( scriptAnalyzerModuleInfo != null )
279
+ if ( hasScriptAnalyzerModule )
307
280
{
308
281
var rules = GetPSScriptAnalyzerRules ( ) ;
309
282
var sb = new StringBuilder ( ) ;
@@ -317,31 +290,14 @@ private void EnumeratePSScriptAnalyzerRules()
317
290
}
318
291
}
319
292
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 > (
338
294
ScriptFile file ,
339
295
string [ ] rules ,
340
296
TSettings settings ) where TSettings : class
341
297
{
342
- IEnumerable < PSObject > diagnosticRecords = Enumerable . Empty < PSObject > ( ) ;
298
+ var diagnosticRecords = new PSObject [ 0 ] ;
343
299
344
- if ( this . scriptAnalyzerModuleInfo != null
300
+ if ( hasScriptAnalyzerModule
345
301
&& ( typeof ( TSettings ) == typeof ( string )
346
302
|| typeof ( TSettings ) == typeof ( Hashtable ) ) )
347
303
{
@@ -375,14 +331,14 @@ private async Task<IEnumerable<PSObject>> GetDiagnosticRecordsAsync<TSettings>(
375
331
return diagnosticRecords ;
376
332
}
377
333
378
- private IEnumerable < PSObject > InvokePowerShell ( string command , IDictionary < string , object > paramArgMap )
334
+ private PSObject [ ] InvokePowerShell ( string command , IDictionary < string , object > paramArgMap )
379
335
{
380
336
var task = InvokePowerShellAsync ( command , paramArgMap ) ;
381
337
task . Wait ( ) ;
382
338
return task . Result ;
383
339
}
384
340
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 )
386
342
{
387
343
using ( var powerShell = System . Management . Automation . PowerShell . Create ( ) )
388
344
{
@@ -396,10 +352,10 @@ private async Task<IEnumerable<PSObject>> InvokePowerShellAsync(string command,
396
352
var result = await Task . Factory . FromAsync ( powerShell . BeginInvoke ( ) , powerShell . EndInvoke ) ;
397
353
if ( result == null )
398
354
{
399
- return Enumerable . Empty < PSObject > ( ) ;
355
+ return new PSObject [ 0 ] ;
400
356
}
401
357
402
- return result ;
358
+ return result . ToArray ( ) ; ;
403
359
}
404
360
}
405
361
0 commit comments