Próbuję napisać niektóre funkcje PowerShell, które robią pewne rzeczy, a następnie jawnie wywołują do istniejących wbudowanych funkcji. Chcę przekazać wszystkie nietknięte argumenty. Nie chcę znać żadnych szczegółów dotyczących argumentów.Jak przekazać "linię argumentu" jednej funkcji PowerShell do innej?
Zmęczony za pomocą "splat" to zrobić z @args
, ale to nie działa tak, jak się spodziewałem.
W poniższym przykładzie napisałem funkcję zabawki o nazwie myls
, która ma wydrukować witam!, a następnie wywołaj tę samą wbudowaną funkcję, Get-ChildItem
, że wbudowany alias ls
dzwoni z pozostałą częścią wiersza argumentu w stanie nienaruszonym. To, co mam do tej pory działa całkiem dobrze:
function myls
{
Write-Output "hello!"
# $MyInvocation | Format-List # <-- uncomment this line for debug info
Invoke-Expression ("Get-ChildItem " + $MyInvocation.UnboundArguments -join " ")
}
Prawidłowa wersja myls
powinien być w stanie obsłużyć miano bez argumentów, z jednym argumentem, z wymienionych argumentów z linii zawierającej wiele średnik rozdzielany poleceń i ze zmiennymi w argumentach, w tym zmiennymi łańcuchowymi zawierającymi spacje. Zasadniczo powinna to być alternatywa w stosunku do ls
. poniżej
Testy porównać myls
a wbudowane ls
:
[UWAGA: Wyjście pomijana i/lub sprasowany w celu zaoszczędzenia miejsca]
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!
Czy istnieje sposób mogę ponownie napisać myls
uzyskać pożądane zachowanie?
Krótka odpowiedź: Tak, jest to możliwe. Złe wieści: wymaga kodu, który zna szczegóły parametrów i innych metadanych dotyczących funkcji, do której chce się zadzwonić. Dobra wiadomość: nie trzeba pisać tego wszystkiego samodzielnie. Te metadane są dostępne programowo i istnieją dostępne moduły, za pomocą których można automatycznie generować szkieletowy kod proxy (patrz odpowiedź @ Jaykul poniżej). Wybieram użycie the module named "MetaProgramming". Po zaimportowaniu generowania drop-in myls
skryptu jest martwy prosta:
New-ProxyCommand ls > .\myls.ps1
Następnie można rozpocząć dostosowywanie nowo wygenerowanego myls.ps1
skrypt tak:
...
begin
{
Write-Output "hello!" # <-- add this line
try {
$outBuffer = $null
...
Voila! Ta nowa wersja przechodzi wszystkie testy.
masz rację, to jest to, czego naprawdę potrzebuję. Dzięki! – jwfearn
Innymi słowy: zautomatyzowane wklejanie kopii. Po prostu zdumiewające. – alecov
Jeśli możesz skopiować i wkleić, nie potrzebujesz generowania kodu. To, co robi OP, próbuje podklasować polecenie: napisanie nowego polecenia na podstawie oryginału, ale z niestandardowymi modyfikacjami ... i skryptem. Jeśli robisz to w języku C#, po prostu odziedziczysz.Ale jesteś w PowerShell, więc musisz napisać funkcję, która zaczyna się od powielenia zestawu parametrów z oryginalnego cmdletu (w PowerShellu nazywamy te funkcje proxy). Jeśli kiedykolwiek istniało coś, co płakało z powodu generowania kodu, to jest to. – Jaykul