私はいくつかのことを行い、既存の組み込み関数を透過的に呼び出すいくつかの PowerShell 関数を作成しようとしています。すべての議論を手付かずのまま伝えたいと思います。引数の詳細を知る必要はありません。
これを行うために「splat」を使用するのにうんざりしまし@args
たが、期待どおりに機能しませんでした。
以下の例では、 hello!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 つの引数、名前付き引数、セミコロンで区切られた複数のコマンドを含む行からの呼び出し、およびスペースを含む文字列変数を含む引数内の変数を使用した呼び出しを処理できる必要があります。基本的には、ドロップインの代わりになるはず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 の回答を参照)。「MetaProgramming」という名前のモジュールを使用することにしました。インポートしたら、ドロップインmyls
スクリプトを生成するのは非常に簡単です。
New-ProxyCommand ls > .\myls.ps1
次に、次のように、新しく生成されmyls.ps1
たスクリプトのカスタマイズを開始できます。
...
begin
{
Write-Output "hello!" # <-- add this line
try {
$outBuffer = $null
...
出来上がり!この新しいバージョンはすべてのテストに合格しています。