2014/04/26
Get-Commandでダイナミックパラメータを表示する方法
小ネタですが。
まず、ダイナミックパラメータについてはぎたぱそ先生の記事を参照してください。要は、その名の通り動的に定義されるパラメータのことです。
ダイナミックパラメータは他の(静的な)パラメータの指定状態によってリアルタイムに定義されます。ValidateSet(値の候補リスト)だけではなく、パラメータの有無、パラメータ値の型やパラメータ名ですら変わり得ます。
一方、Get-Commandコマンドレットを使うとコマンドのパラメータや構文等の情報を取得する事ができます。しかし、ダイナミックパラメータは前述のような特性があるため、パラメータの有無、パラメータ名、パラメータ値の型が一意に定まりません。
この問題を解決するため、Get-Commandコマンドレットには-ArgumentListパラメータが用意されています。指定コマンドに与えるパラメータ値を-ArgumentListパラメータに指定すると、指定コマンド実行時にそのパラメータ値を指定した場合に定義されるダイナミックパラメータに関する情報が、出力結果に含まれるようになります。
例を挙げましょう。Get-Contentコマンドレットの-Pathパラメータは「位置パラメータ」、つまりパラメータ名を省略できるパラメータであり、パラメータ名なしで指定された一つめの値がバインドされます。つまり、 Get-Content C:\ とするとC:\(FileSystemプロバイダのパス)が-Pathパラメータにバインドされるわけです。(Get-Content -Path C:\ と同じ意味となる)
ところでGet-Contentコマンドレットは、FileSystemプロバイダでのみ有効となる-Encodingというダイナミックパラメータを持っています。「FileSystemプロバイダでのみ」というのはつまり、「カレントディレクトリがFileSystemプロバイダのパスであるか、-PathパラメータにFileSystemプロバイダのパスが指定されたとき」ということになります。
すなわち、 カレントディレクトリがC:\であったり、Get-Content C:\ と入力した瞬間、-Encodingダイナミックパラメータが定義されて利用できるようになります。
ではGet-CommandコマンドレットでGet-Contentコマンドレットの-Encodingダイナミックパラメータの情報を得るにはどうすればよいか。答えは、このダイナミックパラメータが定義されるトリガーとなるパラメータ値である「C:\」を-ArgumentListパラメータに指定してやればいいわけです。つまり 例えば
Get-Command -Name Get-Content -ArgumentList C:\ -Syntax
としてやると、Get-Contentコマンドレットの構文が
Get-Content [-Path] <string[]> [-ReadCount <long>] [-TotalCount <long>] [-Tail <int>] [-Filter <string>] [-Include <string[]>] [-Exclude <string[]>] [-Force] [-Credential <pscredential>] [-UseTransaction] [-Delimiter <string>] [-Wait] [-Raw] [-Encoding <FileSystemCmdletProviderEncoding>] [-Stream <string>] [<CommonParameters>]
のように表示され(※注:一部抜粋)、Get-Content C:\を実行するときに定義される-Encodingダイナミックパラメータも含まれていることがわかります。仮にHKLM:\等のFileSystemプロバイダ以外のパスを-ArgumentListに指定すると、
Get-Content [-Path] <string[]>[-ReadCount <long>] [-TotalCount <long>] [-Tail <int>] [-Filter <string>] [-Include <string[]>] [-Exclude <string[]>] [-Force] [-Credential <pscredential>] [-UseTransaction] [<commonparameters>]
のように表示され、ダイナミックパラメータが表示されないことが分かるかと思います。
さて、-ArgumentListは配列指定もでき、複数パラメータ値を指定した時の構文を調べることもできます。しかし位置パラメータ以外の場合、つまりダイナミックパラメータ定義のトリガーとなるパラメータにパラメータ名を指定する必要があるコマンドの場合はどうやら無理のようです。
以下はおまけです。ダイナミックパラメータのリストを表示します。-ArgumentListは指定してないので、カレントディレクトリのプロバイダの種類でのみ結果が変わります。
$cmds = Get-Command -CommandType Cmdlet,Function foreach($cmd in $cmds) { $params = $cmd.Parameters $dynamicParamNames = @() if($null -ne $params) { $dynamicParamNames = @($params.Values|?{$_.IsDynamic}|%{$_.Name}) } if($dynamicParamNames.Length -ne 0) { foreach($dynamicParamName in $dynamicParamNames) { [pscustomobject]@{ Cmdlet=$cmd Module=$cmd.ModuleName Parameter=$dynamicParamName } } } }
まあ本題とあんまり関係なくなってしまったんですが、せっかく作ったのでということで。こういうのを見ると、PowerShellはコマンドもオブジェクトなんだ、ということが分かると思います。
プライバシーポリシー