@@ -38,6 +38,7 @@ public class Helper
3838 private readonly static Version minSupportedPSVersion = new Version ( 3 , 0 ) ;
3939 private Dictionary < string , Dictionary < string , object > > ruleArguments ;
4040 private PSVersionTable psVersionTable ;
41+ private Dictionary < string , CommandInfo > commandInfoCache ;
4142
4243 #endregion
4344
@@ -146,6 +147,7 @@ public void Initialize()
146147 KeywordBlockDictionary = new Dictionary < String , List < Tuple < int , int > > > ( StringComparer . OrdinalIgnoreCase ) ;
147148 VariableAnalysisDictionary = new Dictionary < Ast , VariableAnalysis > ( ) ;
148149 ruleArguments = new Dictionary < string , Dictionary < string , object > > ( StringComparer . OrdinalIgnoreCase ) ;
150+ commandInfoCache = new Dictionary < string , CommandInfo > ( StringComparer . OrdinalIgnoreCase ) ;
149151
150152 IEnumerable < CommandInfo > aliases = this . invokeCommand . GetCommands ( "*" , CommandTypes . Alias , true ) ;
151153
@@ -610,12 +612,16 @@ public bool HasSplattedVariable(CommandAst cmdAst)
610612 /// <returns></returns>
611613 public bool PositionalParameterUsed ( CommandAst cmdAst , bool moreThanThreePositional = false )
612614 {
613- if ( cmdAst == null || cmdAst . GetCommandName ( ) == null )
615+ if ( cmdAst == null )
614616 {
615617 return false ;
616618 }
617619
618- CommandInfo commandInfo = GetCommandInfo ( GetCmdletNameFromAlias ( cmdAst . GetCommandName ( ) ) ) ?? GetCommandInfo ( cmdAst . GetCommandName ( ) ) ;
620+ var commandInfo = GetCommandInfo ( cmdAst . GetCommandName ( ) ) ;
621+ if ( commandInfo == null || ( commandInfo . CommandType != System . Management . Automation . CommandTypes . Cmdlet ) )
622+ {
623+ return false ;
624+ }
619625
620626 IEnumerable < ParameterMetadata > switchParams = null ;
621627
@@ -685,6 +691,23 @@ public bool PositionalParameterUsed(CommandAst cmdAst, bool moreThanThreePositio
685691 }
686692
687693
694+ /// <summary>
695+ /// Get a CommandInfo object of the given command name
696+ /// </summary>
697+ /// <returns>Returns null if command does not exists</returns>
698+ private CommandInfo GetCommandInfoInternal ( string cmdName , CommandTypes ? commandType = null )
699+ {
700+ using ( var ps = System . Management . Automation . PowerShell . Create ( ) )
701+ {
702+ var cmdInfo = ps . AddCommand ( "Get-Command" )
703+ . AddArgument ( cmdName )
704+ . AddParameter ( "ErrorAction" , "SilentlyContinue" )
705+ . Invoke < CommandInfo > ( )
706+ . FirstOrDefault ( ) ;
707+ return cmdInfo ;
708+ }
709+ }
710+
688711 /// <summary>
689712 /// Given a command's name, checks whether it exists
690713 /// </summary>
@@ -693,19 +716,28 @@ public bool PositionalParameterUsed(CommandAst cmdAst, bool moreThanThreePositio
693716 /// <returns></returns>
694717 public CommandInfo GetCommandInfo ( string name , CommandTypes ? commandType = null )
695718 {
696- CommandTypes defaultCmdType = CommandTypes . Alias
697- | CommandTypes . Cmdlet
698- | CommandTypes . ExternalScript
699- | CommandTypes . Filter
700- | CommandTypes . Function
701- | CommandTypes . Script
702- | CommandTypes . Workflow ;
703- #if ! PSV3
704- defaultCmdType |= CommandTypes . Configuration ;
705- #endif
719+ if ( string . IsNullOrWhiteSpace ( name ) )
720+ {
721+ return null ;
722+ }
723+
724+ // check if it is an alias
725+ string cmdletName = Helper . Instance . GetCmdletNameFromAlias ( name ) ;
726+ if ( string . IsNullOrWhiteSpace ( cmdletName ) )
727+ {
728+ cmdletName = name ;
729+ }
730+
706731 lock ( getCommandLock )
707732 {
708- return this . invokeCommand . GetCommand ( name , commandType ?? defaultCmdType ) ;
733+ if ( commandInfoCache . ContainsKey ( cmdletName ) )
734+ {
735+ return commandInfoCache [ cmdletName ] ;
736+ }
737+
738+ var commandInfo = GetCommandInfoInternal ( cmdletName , commandType ) ;
739+ commandInfoCache . Add ( cmdletName , commandInfo ) ;
740+ return commandInfo ;
709741 }
710742 }
711743
0 commit comments