sto cercando di scrivere alcune funzioni PowerShell che fare alcune cose e poi in modo trasparente chiamare fino alle funzioni incorporate esistenti. Voglio passare lungo tutti gli argomenti intatti. Non voglio conoscere alcun dettaglio degli argomenti.Come passare la 'argomento-riga' di una funzione di PowerShell a un'altra?
mi stanco usando 'splat' di fare questo con @args
ma che non ha funzionato come mi aspettavo.
Nell'esempio seguente, ho scritto una funzione giocattolo denominata myls
che dovrebbe stampare ciao! e quindi chiamare la stessa funzione incorporata, Get-ChildItem
, che il ls
chiamate incorporato alias con il resto della linea argomentazione intatta. Quello che ho finora funziona piuttosto bene:
function myls
{
Write-Output "hello!"
# $MyInvocation | Format-List # <-- uncomment this line for debug info
Invoke-Expression ("Get-ChildItem " + $MyInvocation.UnboundArguments -join " ")
}
una versione corretta del myls
dovrebbe essere in grado di gestire essere chiamato senza argomenti, con un argomento, con argomenti con nome, da una linea che contiene più comandi e virgola delimitati e con variabili negli argomenti incluse variabili stringa contenenti spazi. Fondamentalmente, dovrebbe essere un'alternativa drop-in a ls
.
I test di seguito confrontano myls
e integrato ls
:
[NOTA: l'uscita eliso e/o compattata per risparmiare spazio]
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!
C'è un modo per riscrivere myls
ottenere il comportamento che voglio?
Risposta breve: Sì, è possibile. La cattiva notizia: richiede un codice che conosca i dettagli dei parametri e altri metadati relativi alla funzione che si desidera chiamare. La buona notizia: uno non ha bisogno di scrivere tutto questo se stessi. Questi metadati è disponibile programatically ed esistono i moduli disponibili che si possono utilizzare per generare automaticamente codice proxy scheletro (vedi @ risposta di Jaykul sotto). Ho scelto di usare the module named "MetaProgramming". Una volta importati, generando un drop-in myls
script è morto semplice:
New-ProxyCommand ls > .\myls.ps1
Poi si può iniziare a personalizzare il myls.ps1
script appena generati, in questo modo:
...
begin
{
Write-Output "hello!" # <-- add this line
try {
$outBuffer = $null
...
Voila! Questa nuova versione supera tutti i test.
hai ragione questo è ciò di cui ho veramente bisogno. Grazie! – jwfearn
In altre parole: copia-incolla automatizzata. Semplicemente sbalorditivo. – alecov
Se potessi copiare e incollare, non avresti bisogno della generazione del codice. Ciò che l'OP sta facendo è cercare di sottoclasse il comando: scrivere un nuovo comando basato sull'originale, ma con modifiche personalizzate ... e in script. Se lo stavi facendo in C#, ereditavi.Ma sei in PowerShell, quindi devi scrivere una funzione che inizia con la duplicazione del set di parametri dal cmdlet originale (in PowerShell, chiamiamo quelle funzioni proxy). Se c'è mai stato qualcosa che ha pianto per la generazione del codice, è questo. – Jaykul