Richiedi l'input dell'utente in PowerShell


209

Voglio richiedere all'utente una serie di input, tra cui una password e un nome file.

Ho un esempio di utilizzo host.ui.prompt, che sembra ragionevole, ma non riesco a capire il ritorno.

Esiste un modo migliore per ottenere l'input dell'utente in PowerShell?

Risposte:


333

Read-Host è una semplice opzione per ottenere l'input della stringa da un utente.

$name = Read-Host 'What is your username?'

Per nascondere le password puoi usare:

$pass = Read-Host 'What is your password?' -AsSecureString

Per convertire la password in testo semplice:

[Runtime.InteropServices.Marshal]::PtrToStringAuto(
    [Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass))

Per quanto riguarda il tipo restituito da $host.UI.Prompt(), se si esegue il codice sul collegamento pubblicato nel commento di @ Christian, è possibile scoprire il tipo restituito eseguendo il piping su Get-Member(ad esempio $results | gm). Il risultato è un dizionario in cui la chiave è il nome di un FieldDescriptionoggetto utilizzato nel prompt. Per accedere al risultato del primo prompt nell'esempio collegato è necessario digitare: $results['String Field'].

Per accedere alle informazioni senza invocare un metodo, lasciare le parentesi spente:

PS> $Host.UI.Prompt

MemberType          : Method
OverloadDefinitions : {System.Collections.Generic.Dictionary[string,psobject] Pr
                    ompt(string caption, string message, System.Collections.Ob
                    jectModel.Collection[System.Management.Automation.Host.Fie
                    ldDescription] descriptions)}
TypeNameOfValue     : System.Management.Automation.PSMethod
Value               : System.Collections.Generic.Dictionary[string,psobject] Pro
                    mpt(string caption, string message, System.Collections.Obj
                    ectModel.Collection[System.Management.Automation.Host.Fiel
                    dDescription] descriptions)
Name                : Prompt
IsInstance          : True

$Host.UI.Prompt.OverloadDefinitionsti darà la definizione del metodo. Ogni definizione viene visualizzata come <Return Type> <Method Name>(<Parameters>).


Grazie @Rynant. Risposta accettata per essere l'unico che ha effettivamente risposto alla mia domanda principale! ;) Anche tutte le altre informazioni sono davvero utili, specialmente perché mi sto ancora tentando in PS.
AJ.

Nessun problema, @AJ. Un altro modo per ottenere informazioni su un metodo è di lasciare le parentesi. Aggiungerò un esempio alla mia risposta.
Rynant,

3
Cordiali saluti, è anche possibile utilizzare Get-Credential se si ottengono nomi utente e password.
Matt Lyons,

75

L'uso dell'associazione di parametri è sicuramente la strada da percorrere qui. Non solo è molto veloce scrivere (basta aggiungere [Parameter(Mandatory=$true)]sopra i parametri obbligatori), ma è anche l'unica opzione per cui non ti odierai più tardi.

Più sotto:

[Console]::ReadLineè esplicitamente vietato dalle regole di FxCop per PowerShell. Perché? Perché funziona solo in PowerShell.exe, non in PowerShell ISE , PowerGUI , ecc.

Read-Host è, semplicemente, una pessima forma. Read-Host interrompe in modo incontrollato lo script per richiedere all'utente, il che significa che non è mai possibile avere un altro script che includa lo script che utilizza Read-Host.

Stai cercando di chiedere parametri.

È necessario utilizzare l' [Parameter(Mandatory=$true)]attributo e la digitazione corretta per richiedere i parametri.

Se lo usi su a [SecureString], verrà richiesto un campo password. Se lo usi su un tipo di credenziale, ( [Management.Automation.PSCredential]), verrà visualizzata la finestra di dialogo delle credenziali, se il parametro non è presente. Una stringa diventerà semplicemente una vecchia casella di testo. Se aggiungi un HelpMessage all'attributo parametro (ovvero, [Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]) diventerà il testo di aiuto per il prompt.


5
Questa è la soluzione più flessibile e intuitiva , ma ho quasi ignorato il tuo consiglio perché non c'erano esempi di codice chiari come nella risposta di Rynant . Puoi fornire alcuni esempi ben formattati?
Iain Samuel McLean Elder,

4
"Read-Host è, in parole povere, forma sbagliata" ... a meno che tu non lo stia usando per accettare condizionalmente l'input che è stato escluso perché qualcuno non stava chiamando il tuo script con QUALSIASI parametro. BOOM.

2
No: allora è ancora una cattiva forma. Ecco perché contrassegni i parametri come obbligatori.
Inizia ad automatizzare il

2
Cosa succede se si desidera scrivere uno script interattivo? Supponiamo che sia uno script che richiede l'input dell'utente solo se sono soddisfatte determinate condizioni. Ad esempio, se lo script deve impostare una directory di destinazione per un SDK, è possibile confermare che l'utente desidera eliminare la directory se esiste già.
Jason Goemaat,

6
Penso che user1499731 abbia avuto un buon punto ... Ci sono momenti in cui è necessario ricevere input dall'utente che possono essere forniti in modo significativo solo dopo che sono state visualizzate alcune informazioni o è stata eseguita un'altra operazione. In tal caso, non è possibile utilizzare un parametro e i motivi indicati qui per Read-Hostessere "cattiva forma" non si applicano. Inoltre, .ShouldProcess()ha delle restrizioni che Read-Hostnon lo sono, come essere limitato a poche risposte. Tuttavia sono d'accordo che .ShouldProcess()è meglio, quando è applicabile.
LarsH,

14

Posizionalo nella parte superiore della tua sceneggiatura. Lo script richiederà all'utente una password. La password risultante può quindi essere utilizzata altrove nello script tramite $ pw .

   Param(
     [Parameter(Mandatory=$true, Position=0, HelpMessage="Password?")]
     [SecureString]$password
   )

   $pw = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))

Se desideri eseguire il debug e visualizzare il valore della password che hai appena letto, utilizza:

   write-host $pw

3

In alternativa, è possibile aggiungerlo come parametro di script per l'input come parte dell'esecuzione dello script

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )
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.