@@ -158,7 +158,7 @@ private void SetupPSSAAppData()
158
158
SetupTempDir ( ) ;
159
159
}
160
160
161
- private bool IsModulePresent ( string moduleName )
161
+ private bool IsModulePresentInTempModulePath ( string moduleName )
162
162
{
163
163
foreach ( var dir in Directory . EnumerateDirectories ( TempModulePath ) )
164
164
{
@@ -335,7 +335,7 @@ public bool TrySaveModule(string moduleName)
335
335
public void SaveModule ( string moduleName )
336
336
{
337
337
ThrowIfNull ( moduleName , "moduleName" ) ;
338
- if ( IsModulePresent ( moduleName ) )
338
+ if ( IsModulePresentInTempModulePath ( moduleName ) )
339
339
{
340
340
return ;
341
341
}
@@ -350,6 +350,60 @@ public void SaveModule(string moduleName)
350
350
}
351
351
}
352
352
353
+ /// <summary>
354
+ /// Encapsulates Get-Module to check the availability of the module on the system
355
+ /// </summary>
356
+ /// <param name="moduleName"></param>
357
+ /// <returns>True indicating the presence of the module, otherwise false</returns>
358
+ public bool IsModuleAvailable ( string moduleName )
359
+ {
360
+ ThrowIfNull ( moduleName , "moduleName" ) ;
361
+ IEnumerable < PSModuleInfo > availableModules ;
362
+ using ( var ps = System . Management . Automation . PowerShell . Create ( ) )
363
+ {
364
+ ps . Runspace = runspace ;
365
+ availableModules = ps . AddCommand ( "Get-Module" )
366
+ . AddParameter ( "Name" , moduleName )
367
+ . AddParameter ( "ListAvailable" )
368
+ . Invoke < PSModuleInfo > ( ) ;
369
+ }
370
+ return availableModules != null ? availableModules . Any ( ) : false ;
371
+ }
372
+
373
+ /// <summary>
374
+ /// Extracts out the module names from the error extent that are not available
375
+ ///
376
+ /// This handles the following case.
377
+ /// Import-DSCResourceModule -ModuleName ModulePresent,ModuleAbsent
378
+ ///
379
+ /// ModulePresent is present in PSModulePath whereas ModuleAbsent is not.
380
+ /// But the error exent coverts the entire extent and hence we need to check
381
+ /// which module is actually not present so as to be downloaded
382
+ /// </summary>
383
+ /// <param name="error"></param>
384
+ /// <param name="ast"></param>
385
+ /// <returns>An enumeration over the module names that are not available</returns>
386
+ public IEnumerable < string > GetUnavailableModuleNameFromErrorExtent ( ParseError error , ScriptBlockAst ast )
387
+ {
388
+ ThrowIfNull ( error , "error" ) ;
389
+ ThrowIfNull ( ast , "ast" ) ;
390
+ var moduleNames = ModuleDependencyHandler . GetModuleNameFromErrorExtent ( error , ast ) ;
391
+ if ( moduleNames == null )
392
+ {
393
+ return null ;
394
+ }
395
+ var unavailableModules = new List < string > ( ) ;
396
+ foreach ( var moduleName in moduleNames )
397
+ {
398
+ if ( ! IsModuleAvailable ( moduleName ) )
399
+ {
400
+ unavailableModules . Add ( moduleName ) ;
401
+ }
402
+ }
403
+ //return moduleNames.Where(x => !IsModuleAvailable(x));
404
+ return unavailableModules ;
405
+ }
406
+
353
407
/// <summary>
354
408
/// Get the module name from the error extent
355
409
///
@@ -362,7 +416,7 @@ public void SaveModule(string moduleName)
362
416
/// <param name="error">Parse error</param>
363
417
/// <param name="ast">AST of the script that contians the parse error</param>
364
418
/// <returns>The name of the module that caused the parser to throw the error. Returns null if it cannot extract the module name.</returns>
365
- public static string GetModuleNameFromErrorExtent ( ParseError error , ScriptBlockAst ast )
419
+ public static IEnumerable < string > GetModuleNameFromErrorExtent ( ParseError error , ScriptBlockAst ast )
366
420
{
367
421
ThrowIfNull ( error , "error" ) ;
368
422
ThrowIfNull ( ast , "ast" ) ;
@@ -373,9 +427,10 @@ public static string GetModuleNameFromErrorExtent(ParseError error, ScriptBlockA
373
427
return null ;
374
428
}
375
429
// check if the command name is import-dscmodule
376
- // right now we handle only the following form
377
- // Import-DSCResource -ModuleName xActiveDirectory
378
- if ( dynamicKywdAst . CommandElements . Count != 3 )
430
+ // right now we handle only the following forms
431
+ // 1. Import-DSCResourceModule -ModuleName somemodule
432
+ // 2. Import-DSCResourceModule -ModuleName somemodule1,somemodule2
433
+ if ( dynamicKywdAst . CommandElements . Count < 3 )
379
434
{
380
435
return null ;
381
436
}
@@ -386,19 +441,56 @@ public static string GetModuleNameFromErrorExtent(ParseError error, ScriptBlockA
386
441
return null ;
387
442
}
388
443
389
- var paramAst = dynamicKywdAst . CommandElements [ 1 ] as CommandParameterAst ;
390
- if ( paramAst == null || ! paramAst . ParameterName . Equals ( "ModuleName" , StringComparison . OrdinalIgnoreCase ) )
444
+ // find a parameter named modulename
445
+ int k ;
446
+ for ( k = 1 ; k < dynamicKywdAst . CommandElements . Count ; k ++ )
391
447
{
392
- return null ;
448
+ var paramAst = dynamicKywdAst . CommandElements [ 1 ] as CommandParameterAst ;
449
+ // TODO match the initial letters only
450
+ if ( paramAst == null || ! paramAst . ParameterName . Equals ( "ModuleName" , StringComparison . OrdinalIgnoreCase ) )
451
+ {
452
+ continue ;
453
+ }
454
+ break ;
393
455
}
394
-
395
- var paramValAst = dynamicKywdAst . CommandElements [ 2 ] as StringConstantExpressionAst ;
396
- if ( paramValAst == null )
456
+
457
+ if ( k == dynamicKywdAst . CommandElements . Count )
397
458
{
459
+ // cannot find modulename
398
460
return null ;
399
461
}
462
+ var modules = new List < string > ( ) ;
463
+
464
+ // k < count - 1, because only -ModuleName throws parse error and hence not possible
465
+ var paramValAst = dynamicKywdAst . CommandElements [ ++ k ] ;
400
466
401
- return paramValAst . Value ;
467
+ // import-dscresource -ModuleName module1
468
+ var paramValStrConstExprAst = paramValAst as StringConstantExpressionAst ;
469
+ if ( paramValStrConstExprAst != null )
470
+ {
471
+ modules . Add ( paramValStrConstExprAst . Value ) ;
472
+ return modules ;
473
+ }
474
+
475
+ // import-dscresource -ModuleName module1,module2
476
+ var paramValArrLtrlAst = paramValAst as ArrayLiteralAst ;
477
+ if ( paramValArrLtrlAst != null )
478
+ {
479
+ foreach ( var elem in paramValArrLtrlAst . Elements )
480
+ {
481
+ var elemStrConstExprAst = elem as StringConstantExpressionAst ;
482
+ if ( elemStrConstExprAst != null )
483
+ {
484
+ modules . Add ( elemStrConstExprAst . Value ) ;
485
+ }
486
+ }
487
+ if ( modules . Count == 0 )
488
+ {
489
+ return null ;
490
+ }
491
+ return modules ;
492
+ }
493
+ return null ;
402
494
}
403
495
404
496
/// <summary>
0 commit comments