Jak obsługiwać argumenty wiersza polecenia w programie PowerShell

494

Jaki jest „najlepszy” sposób obsługi argumentów wiersza poleceń?

Wygląda na to, że istnieje kilka odpowiedzi na to, co jest „najlepszym” sposobem, dlatego utknąłem na tym, jak poradzić sobie z czymś tak prostym, jak:

script.ps1 /n name /d domain

I

script.ps1 /d domain /n name.

Czy istnieje wtyczka, która poradzi sobie z tym lepiej? Wiem, że tutaj odkrywam koło.

Oczywiście to, co już mam, nie jest ładne i na pewno nie jest „najlepsze”, ale działa… i jest Brzydkie.

for ( $i = 0; $i -lt $args.count; $i++ ) {
    if ($args[ $i ] -eq "/n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "/d"){ $strDomain=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-d"){ $strDomain=$args[ $i+1 ]}
}
Write-Host $strName
Write-Host $strDomain
Aaron Wurthmann
źródło

Odpowiedzi:

917

Wymyślasz koło na nowo. Normalne skrypty PowerShell mają parametry zaczynające się od -, npscript.ps1 -server http://devserver

Następnie zajmujesz się nimi w paramsekcji na początku pliku.

Możesz także przypisać wartości domyślne do swoich parametrów, odczytać je z konsoli, jeśli nie są dostępne, lub zatrzymać wykonywanie skryptu:

 param (
    [string]$server = "http://defaultserver",
    [Parameter(Mandatory=$true)][string]$username,
    [string]$password = $( Read-Host "Input password, please" )
 )

Wewnątrz skryptu możesz po prostu

write-output $server

ponieważ wszystkie parametry stają się zmiennymi dostępnymi w zakresie skryptu.

W tym przykładzie $serverwartość domyślna jest -usernamepobierana, jeśli skrypt jest wywoływany bez niego, skrypt zatrzymuje się, jeśli pominiesz parametr, i poprosi o wprowadzenie danych terminalowych, jeśli -passwordzostanie pominięty.

Aktualizacja: Możesz także przekazać „flagę” (boolowski parametr prawda / fałsz) do skryptu PowerShell. Na przykład skrypt może zaakceptować „siłę”, w której skrypt działa w trybie bardziej ostrożnym, gdy siła nie jest używana.

Słowem kluczowym do tego jest [switch]typ parametru:

 param (
    [string]$server = "http://defaultserver",
    [string]$password = $( Read-Host "Input password, please" ),
    [switch]$force = $false
 )

Wewnątrz skryptu pracowałbyś z nim w ten sposób:

if ($force) {
  //deletes a file or does something "bad"
}

Teraz, wywołując skrypt, ustawiłeś parametr switch / flag w następujący sposób:

.\yourscript.ps1 -server "http://otherserver" -force

Jeśli chcesz wyraźnie stwierdzić, że flaga nie jest ustawiona, istnieje specjalna specjalna składnia

.\yourscript.ps1 -server "http://otherserver" -force:$false

Odnośniki do odpowiedniej dokumentacji Microsoft (dla PowerShell 5.0; wersje 3.0 i 4.0 są również dostępne pod odnośnikami):

naiwiści
źródło
58
Rzeczywiście jedną z wielkich zalet programu PowerShell jest to, że zapewnia on łatwą w użyciu infrastrukturę do analizy parametrów standardowych.
Keith Hill
14
@naivists z PowerShell 2.0 zamiast [string]$username = $(throw "-username is required.")tam jest składnia dla obowiązkowych parametrów: [Parameter(Mandatory=$true)][string]$username. Oto więcej informacji o różnicach między tymi technikami: blogs.technet.com/b/heyscriptingguy/archive/2011/05/22/…
v.karbovnichy
7
Uważaj na błąd, gdy arg nie zostanie dostarczony; PowerShell po prostu pobierze dodatkowy tekst z wiersza poleceń:. \ yourscript.ps1 -server " serv " -password "mypass" literówka To magicznie przypisze literówkę do $ username.
sheamus
4
Jednak użycie bloku parametrów wydaje się mieć inne niezamierzone konsekwencje: stackoverflow.com/questions/40940819/…
Logan
1
@sheamus: to nie jest błąd! Program Powershell przetwarza i przypisuje argumenty w podanej kolejności, chyba że zostanie to zastąpione przez użycie poprawnej nazwy parametru, np. Jeśli lista bloków parametrów zawiera: $ user $ pass $ server, a ty wykonasz skrypt yourscript.ps1 abc, a będzie ustaw na $ user, b na $ pass ic na serwer $, chyba że specjalnie je przypisałeś! Więc jeśli powiesz: yourscript.ps1 -pass abc, $ pass zostanie ustawione na a, a pozostałe (nienazwane) parametry zostaną użyte do uzupełnienia brakujących, w kolejności podanej w bloku parametrów, więc $ user = b, $ serwer = c.
Fernando Madruga