あるPowerShell関数の「引数」を別のパワーシェル関数に渡す方法は?

StackOverflow https://stackoverflow.com/questions/4702406

質問

私はいくつかのことを行ういくつかのPowerShell関数を書き込もうとしています。その後、既存の組み込み関数に透過的に呼び出します。手付かずのすべての議論を伝えたいです。私は議論の詳細を知りたくありません。

私はこれを行うために「スプラット」を使って疲れました @args しかし、それは私が思っていたようにうまくいきませんでした。

以下の例では、私は呼ばれるおもちゃ機能を書きました myls 印刷することになっている こんにちは! そして、同じ組み込み関数を呼び出し、 Get-ChildItem, 、組み込みエイリアス ls 引数の残りの部分との呼び出しはそのままです。私がこれまでに持っているものは非常にうまく機能します:

function myls
{
  Write-Output "hello!"
# $MyInvocation | Format-List          # <-- uncomment this line for debug info
  Invoke-Expression ("Get-ChildItem " + $MyInvocation.UnboundArguments -join " ")
}

の正しいバージョン myls 複数のセミコロン区切りコマンドを含む行から、1つの引数、名前の引数で、1つの引数で、1つの引数で、1つの引数で、およびスペースを含む文字列変数を含む引数の変数を処理できる必要があります。基本的に、それはドロップインの代替品である必要があります ls.

以下のテストは比較します myls そしてビルトイン ls:

注:スペースを節約するために排除および/または圧縮された出力

PS> md C:\p\d\x, C:\p\d\y, C:\p\d\"jay z"
PS> cd C:\p\d
PS> ls                                 # no args
PS> myls                               # pass
PS> cd ..
PS> ls d                               # one arg
PS> myls d                             # pass
PS> $a="A"; $z="Z"; $y="y"; $jz="jay z"
PS> $a; ls d; $z                       # multiple statements
PS> $a; myls d; $z                     # pass
PS> $a; ls d -Exclude x; $z            # named args
PS> $a; myls d -Exclude x; $z          # pass
PS> $a; ls d -Exclude $y; $z           # variables in arg-line
PS> $a; myls d -Exclude $y; $z         # pass
PS> $a; ls d -Exclude $jz; $z          # variables containing spaces in arg-line
PS> $a; myls d -Exclude $jz; $z        # FAIL!

私が書き直すことができる方法はありますか? myls 私が欲しい行動を取得するには?

短い答え: はい、それは可能です。悪いニュース:呼び出したい関数に関するパラメーターやその他のメタデータの詳細を知っているコードが必要です。良いニュース: これをすべて自分で書く必要はありません. 。このメタデータはプログラムで利用可能であり、スケルトンプロキシコードを自動生成するために使用できるモジュールが存在します(以下の @jaykulの回答を参照)。使用することを選択します 「メタプログラム」という名前のモジュール. 。インポートしたら、ドロップインを生成します myls スクリプトはシンプルです:

New-ProxyCommand ls > .\myls.ps1

その後、新しく生成されたカスタマイズを開始できます myls.ps1 スクリプト、このような:

  ...
  begin
  {
    Write-Output "hello!"              # <-- add this line
    try {
      $outBuffer = $null
  ...

出来上がり!この新しいバージョンはすべてのテストに合格します。

役に立ちましたか?

解決

LSのドロップインラッパーが必要な場合は、 適切なプロキシ関数. 。 poshcode.orgには、ジェネレーターにはいくつかのバージョンがあります。 Lee HolmesのPowershell Cookbookのもの

他のヒント

残念ながら、ラッパーを適切に作るのはそれほど簡単ではありません。まず第一に、Splat演算子はおそらくハッシュテーブルに適用する必要があります(例:自動 PSBoundParameters または別の)、配列ではなく $args 直接。

少なくとも2つのオプション(両方とも完璧ではありません)とハック(更新セクションを参照)があります。

オプション1.ラッパーを作成する「クラシック」方法を使用します。例:これが関数に対してどのように行われるかを参照してください help これはのラッパーです Get-Help cmdlet:

Get-Content function:\help

ラッパー機能宣言者がわかります すべて ラップされたcmdletがそれを持つために持っているパラメーター PSBoundParameters 既存の関数パラメーターに制限されています.

あなたの例。関数がパラメーターを宣言する場合 Exclude 次に、サンプルコードが機能し始めます。しかし、それは機能します Exclude のみ、そうではありません Force, 、 けれど Force 渡されます:

function myls($Exclude) {
    # only Exclude is in $PSBoundParameters even though we send Force, too:
    $PSBoundParameters | Out-String | Out-Host
    Write-Output "hello!"
    Get-ChildItem @PSBoundParameters
}
cd d
myls -Exclude b -Force

オプション2.理論的には、配列からハッシュテーブルを構築することができるはずです $args 手動でスプラット演算子を適用します。しかし、このタスクは実質的に魅力的ではありません。


アップデート

まあ、実際には、最小限の労力を必要とする別のアドホックオプション(純粋なハック!)があり、いくつかの些細な、ほとんどインタラクティブなシナリオで機能します。それは何らかの形で深刻なコードのためではありません!

function myls {
    # extra job
    Write-Output "hello!"

    # invoke/repeat the calling code line with myls "replaced" with Get-ChildItem
    Set-Alias myls Get-ChildItem
    Invoke-Expression $MyInvocation.Line
}

cd d

# variables can be used as the parameter values, too
$exclude = 'b'

myls -Exclude $exclude -Force

私はこれを信じています:

function myls {write-output "hello!"; iex "get-childitem @args"}

期待される結果の生成に近づきます。

更新:この方法で @argsを使用して名前のパラメーターを渡すことで、明らかに既知のバグがあります。

https://connect.microsoft.com/powershell/feedback/details/368512/splat-operator-args-doesnt-properly-pass-named-arguments?wa=wsignin1.0

それが解決されるまでそれを使用することを中止します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top