Monituj o dane wprowadzane przez użytkownika w programie PowerShell

209

Chcę zapytać użytkownika o szereg danych wejściowych, w tym hasło i nazwę pliku.

Mam przykład użycia host.ui.prompt, co wydaje się rozsądne, ale nie rozumiem zwrotu.

Czy jest lepszy sposób na uzyskanie wkładu użytkownika w PowerShell?

AJ
źródło

Odpowiedzi:

333

Read-Host jest prostą opcją do uzyskiwania danych wejściowych od użytkownika.

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

Aby ukryć hasła, możesz użyć:

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

Aby przekonwertować hasło na zwykły tekst:

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

Jeśli chodzi o typ zwracany przez $host.UI.Prompt(), jeśli uruchomisz kod pod linkiem opublikowanym w komentarzu @ Christiana, możesz znaleźć typ zwrotu, przesyłając go do Get-Member(na przykład $results | gm). Wynikiem jest Słownik, w którym klucz jest nazwą FieldDescriptionobiektu użytego w pytaniu. Aby uzyskać dostęp do wyniku pierwszego monitu w połączonym przykładzie, należy wpisać:$results['String Field'] .

Aby uzyskać dostęp do informacji bez wywoływania metody, pozostaw nawiasy wyłączone:

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.OverloadDefinitionspoda definicję metody. Każda definicja jest wyświetlana jako <Return Type> <Method Name>(<Parameters>).

Rynant
źródło
Dzięki, @Rynant. Zaakceptowana odpowiedź za to, że jako jedyna faktycznie odpowiedziała na moje główne pytanie! ;) Wszystkie inne informacje też są bardzo pomocne, zwłaszcza, że ​​wciąż szukam PS.
AJ.
Nie ma problemu, @AJ. Innym sposobem na uzyskanie informacji o metodzie jest pominięcie nawiasów. Dodaję przykład do mojej odpowiedzi.
Rynant
3
Do Twojej wiadomości możesz także użyć Get-Credential, jeśli otrzymujesz nazwy użytkownika i hasła.
Matt Lyons,
75

Korzystanie z wiązania parametrów jest zdecydowanie najlepszym sposobem na przejście tutaj. Pisanie jest nie tylko bardzo szybkie (wystarczy dodać[Parameter(Mandatory=$true)] powyżej swoich obowiązkowych parametrów), ale jest to również jedyna opcja, której nie będziesz nienawidzić później.

Więcej poniżej:

[Console]::ReadLinejest wyraźnie zabronione przez reguły FxCop dla PowerShell. Czemu? Ponieważ działa tylko w PowerShell.exe, a nie PowerShell ISE , PowerGUI itp.

Read-Host to po prostu zła forma. Read-Host w niekontrolowany sposób zatrzymuje skrypt, aby monitować użytkownika, co oznacza, że ​​nigdy nie możesz mieć innego skryptu zawierającego skrypt korzystający z Read-Host.

Próbujesz zapytać o parametry.

Powinieneś użyć [Parameter(Mandatory=$true)] atrybutu i poprawić pisanie, aby zapytać o parametry.

Jeśli użyjesz tego w polu [SecureString], pojawi się monit o podanie hasła. Jeśli użyjesz tego typu poświadczenia ( [Management.Automation.PSCredential]), pojawi się okno dialogowe poświadczeń, jeśli nie ma tam parametru. Ciąg stanie się zwykłym starym polem tekstowym. Jeśli dodasz HelpMessage do atrybutu parametru (to znaczy [Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]), stanie się on tekstem pomocy dla monitu.

Rozpocznij automatyzację
źródło
5
Jest to najbardziej elastyczne i przyjazne dla użytkownika rozwiązanie, ale prawie zignorowałem twoją radę, ponieważ nie było wyraźnych przykładów kodu, takich jak odpowiedź Rynant . Czy możesz podać jakieś dobrze sformatowane przykłady?
Iain Samuel McLean Starszy
4
„Read-Host to po prostu zła forma” ... chyba że używasz go do warunkowego akceptowania danych wejściowych, które zostały pominięte, ponieważ ktoś nie wywoływał twojego skryptu z ŻADNYMI parametrami. BUM.
2
Nie: to wciąż jest zła forma. Dlatego zaznaczasz parametry jako obowiązkowe.
Rozpocznij automatyzację
2
Co jeśli chcesz napisać interaktywny skrypt? Powiedzmy, że jest to skrypt, który wymaga danych wejściowych użytkownika tylko wtedy, gdy spełnione są określone warunki. Na przykład, jeśli skrypt ma skonfigurować katalog docelowy dla zestawu SDK, możesz chcieć potwierdzić, że użytkownik chce usunąć katalog, jeśli już istnieje.
Jason Goemaat,
6
Myślę, że użytkownik 1499731 miał rację ... Są chwile, kiedy trzeba wziąć od użytkownika dane wejściowe, które można sensownie podać tylko po wyświetleniu niektórych informacji lub wykonaniu innej operacji. W takim przypadku nie można użyć parametru, a podane tutaj przyczyny Read-Host„złej formy” nie mają zastosowania. Co więcej, .ShouldProcess()ma ograniczenia, których Read-Hostnie ma, na przykład ogranicza się do kilku odpowiedzi. Zgadzam się jednak, że .ShouldProcess()lepiej, jeśli ma to zastosowanie.
LarsH
14

Umieść to na górze skryptu. Spowoduje to, że skrypt wyświetli monit o podanie hasła. Wynikowe hasło można następnie wykorzystać w innym miejscu skryptu za pomocą $ pw .

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

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

Jeśli chcesz debugować i zobaczyć wartość właśnie przeczytanego hasła, użyj:

   write-host $pw
użytkownik2334160
źródło
3

Alternatywnie możesz dodać go jako parametr skryptu do wprowadzania w ramach wykonywania skryptu

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )
Politycznie niezależny
źródło