Eingabeaufforderung zur Benutzereingabe in PowerShell

209

Ich möchte den Benutzer zur Eingabe einer Reihe von Eingaben auffordern, einschließlich eines Kennworts und eines Dateinamens.

Ich habe ein Beispiel für die Verwendung host.ui.prompt, das sinnvoll erscheint, aber ich kann die Rückkehr nicht verstehen.

Gibt es eine bessere Möglichkeit, Benutzereingaben in PowerShell abzurufen?

AJ.
quelle

Antworten:

333

Read-Host ist eine einfache Option zum Abrufen von Zeichenfolgen von einem Benutzer.

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

So verstecken Sie Passwörter:

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

So konvertieren Sie das Passwort in Klartext:

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

Wie für den Typen zurück durch $host.UI.Prompt(), wenn Sie den Code auf dem Link gepostet in @ Christian Kommentar ausführen, können Sie den Rückgabetyp von Rohrleitungen , es herauszufinden Get-Member(zum Beispiel $results | gm). Das Ergebnis ist ein Wörterbuch, in dem der Schlüssel der Name eines FieldDescriptionObjekts ist, das in der Eingabeaufforderung verwendet wird. Um auf das Ergebnis für die erste Eingabeaufforderung im verknüpften Beispiel zuzugreifen, geben Sie Folgendes ein : $results['String Field'].

Lassen Sie die Klammern weg, um auf Informationen zuzugreifen, ohne eine Methode aufzurufen:

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.OverloadDefinitionsgibt Ihnen die Definition (en) der Methode. Jede Definition wird als angezeigt <Return Type> <Method Name>(<Parameters>).

Rynant
quelle
Danke, @Rynant. Akzeptierte Antwort als einziger, der meine Hauptfrage tatsächlich beantwortet hat! ;) Alle anderen Informationen sind auch sehr hilfreich, zumal ich mich immer noch in PS zurechtfinde.
AJ.
Kein Problem, @AJ. Eine andere Möglichkeit, Informationen zu einer Methode zu erhalten, besteht darin, die Klammern wegzulassen. Ich werde meiner Antwort ein Beispiel hinzufügen.
Rynant
3
Zu Ihrer Information, Sie können Get-Credential auch verwenden, wenn Sie Benutzernamen und Passwörter erhalten.
Matt Lyons
75

Die Verwendung der Parameterbindung ist hier definitiv der richtige Weg. Es ist nicht nur sehr schnell zu schreiben (fügen [Parameter(Mandatory=$true)]Sie einfach über Ihren obligatorischen Parametern hinzu), sondern es ist auch die einzige Option, die Sie später nicht hassen werden.

Mehr unten:

[Console]::ReadLineist durch die FxCop- Regeln für PowerShell ausdrücklich verboten . Warum? Da es nur in PowerShell.exe funktioniert, nicht in PowerShell ISE , PowerGUI usw.

Read-Host ist ganz einfach eine schlechte Form. Read-Host stoppt das Skript unkontrolliert, um den Benutzer aufzufordern. Dies bedeutet, dass Sie niemals ein anderes Skript haben können, das das Skript enthält, das Read-Host verwendet.

Sie versuchen, nach Parametern zu fragen.

Sie sollten das [Parameter(Mandatory=$true)]Attribut und die korrekte Eingabe verwenden, um nach den Parametern zu fragen.

Wenn Sie dies für a verwenden [SecureString], werden Sie zur Eingabe eines Kennwortfelds aufgefordert. Wenn Sie dies für einen Anmeldeinformationstyp ( [Management.Automation.PSCredential]) verwenden, wird das Anmeldeinformationsdialogfeld angezeigt, wenn der Parameter nicht vorhanden ist. Eine Zeichenfolge wird einfach zu einem einfachen alten Textfeld. Wenn Sie dem Parameterattribut (dh) eine HelpMessage hinzufügen, wird diese zum Hilfetext [Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]für die Eingabeaufforderung.

Starten Sie die Automatisierung
quelle
5
Dies ist die flexibelste und benutzerfreundlichste Lösung, aber ich habe Ihren Rat fast ignoriert, da es keine klaren Codebeispiele wie in Rynants Antwort gab. Können Sie einige schön formatierte Beispiele liefern?
Iain Samuel McLean Elder
4
"Read-Host ist ganz einfach eine schlechte Form" ... es sei denn, Sie verwenden sie, um bedingte Eingaben zu akzeptieren, die ausgelassen wurden, weil jemand Ihr Skript nicht mit irgendwelchen Parametern aufgerufen hat. BOOM.
2
Nein, dann ist es immer noch eine schlechte Form. Deshalb markieren Sie Parameter als obligatorisch.
Beginnen Sie mit der Automatisierung
2
Was ist, wenn Sie ein interaktives Skript schreiben möchten ? Angenommen, es handelt sich um ein Skript, für das nur Benutzereingaben erforderlich sind, wenn bestimmte Bedingungen erfüllt sind. Wenn Ihr Skript beispielsweise ein Zielverzeichnis für ein SDK einrichten soll, möchten Sie möglicherweise bestätigen, dass der Benutzer das Verzeichnis löschen möchte, falls es bereits vorhanden ist.
Jason Goemaat
6
Ich denke , user1499731 einen guten Punkt hatte ... Es gibt Zeiten, wenn Sie eine Eingabe vom Benutzer zu übernehmen müssen , die nur sinnvoll zur Verfügung gestellt werden können , nachdem einige Informationen angezeigt werden oder eine weitere Operation durchgeführt wird. In diesem Fall können Sie keinen Parameter verwenden, und die hier angegebenen Gründe für Read-Hostdie "schlechte Form" gelten nicht. Darüber hinaus .ShouldProcess()gibt es Einschränkungen, die Read-Hostdies nicht tun, z. B. die Beschränkung auf nur wenige Antworten. Ich stimme jedoch zu, dass dies .ShouldProcess()besser ist, wenn es anwendbar ist.
LarsH
14

Platzieren Sie dies oben in Ihrem Skript. Das Skript fordert den Benutzer zur Eingabe eines Kennworts auf. Das resultierende Passwort kann dann über $ pw an anderer Stelle in Ihrem Skript verwendet werden .

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

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

Wenn Sie debuggen und den Wert des gerade gelesenen Kennworts anzeigen möchten, verwenden Sie:

   write-host $pw
user2334160
quelle
3

Alternativ können Sie es als Skriptparameter für die Eingabe im Rahmen der Skriptausführung hinzufügen

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )
Einzelgänger
quelle