Come gestire gli argomenti della riga di comando in PowerShell


494

Qual è il modo "migliore" per gestire gli argomenti della riga di comando?

Sembra che ci siano diverse risposte su quale sia il modo "migliore" e di conseguenza sono bloccato su come gestire qualcosa di semplice come:

script.ps1 /n name /d domain

E

script.ps1 /d domain /n name.

Esiste un plugin in grado di gestirlo meglio? So che sto reinventando la ruota qui.

Ovviamente quello che ho già non è carino e sicuramente non è il "migliore", ma funziona .. ed è BRUTTO.

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

Risposte:


917

Stai reinventando la ruota. Gli script normali di PowerShell hanno parametri che iniziano con -, comescript.ps1 -server http://devserver

Quindi li gestisci nella paramsezione all'inizio del file.

Puoi anche assegnare valori predefiniti ai tuoi parametri, leggerli dalla console se non disponibili o interrompere l'esecuzione dello script:

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

All'interno della sceneggiatura puoi semplicemente

write-output $server

poiché tutti i parametri diventano variabili disponibili nell'ambito dello script.

In questo esempio, $serverottiene un valore predefinito se lo script viene chiamato senza di esso, lo script si interrompe se si omette il -usernameparametro e chiede l'input del terminale se -passwordviene omesso.

Aggiornamento: potresti anche voler passare un "flag" (un parametro booleano true / false) a uno script di PowerShell. Ad esempio, lo script può accettare una "forza" in cui lo script viene eseguito in una modalità più accurata quando non viene utilizzata la forza.

La parola chiave per questo è [switch]tipo di parametro:

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

All'interno dello script quindi lavoreresti in questo modo:

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

Ora, quando si chiama lo script, si imposta il parametro switch / flag in questo modo:

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

Se si desidera esplicitamente affermare che il flag non è impostato, esiste una sintassi speciale per questo

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

Collegamenti alla documentazione Microsoft pertinente (per PowerShell 5.0; anche le versioni 3.0 e 4.0 sono disponibili sui collegamenti):


58
In effetti uno dei grandi vantaggi di PowerShell è che fornisce un parametro standard che analizza l'infrastruttura che è facile da usare.
Keith Hill,

14
@naivists, da PowerShell 2.0, invece di [string]$username = $(throw "-username is required.")v'è la sintassi per i parametri obbligatori: [Parameter(Mandatory=$true)][string]$username. Ecco maggiori informazioni sulla differenza tra queste tecniche: blogs.technet.com/b/heyscriptingguy/archive/2011/05/22/…
v.karbovnichy

7
Diffidare del bug quando non viene fornito un arg; powershell prenderà semplicemente qualsiasi testo aggiuntivo dalla riga di comando:. \ yourscript.ps1 -server " serv " -password "mypass" typo Questo assegnerà magicamente 'typo' a $ username.
sheamus,

4
L'uso di un blocco param sembra avere altre conseguenze indesiderate: stackoverflow.com/questions/40940819/…
Logan

1
@sheamus: non è un bug! Powershell elaborerà e assegnerà gli argomenti nell'ordine in cui sono stati forniti, a meno che non vengano sovrascritti utilizzando il nome del parametro corretto, ad esempio, se il tuo blocco di parametri elenca: $ user $ pass $ server e esegui yourscript.ps1 abc, un sarà impostato in $ user, b in $ pass e c in $ server, A MENO CHE non li assegni specificamente! Quindi, se dici: yourscript.ps1 -pass abc, $ pass verrà impostato su a, e i restanti parametri (senza nome) verranno utilizzati per riempire quelli mancanti, nell'ordine elencato nel blocco parametri, quindi $ user = b, $ server = c.
Fernando Madruga,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.