Meminta input pengguna di PowerShell

209

Saya ingin meminta pengguna untuk serangkaian input, termasuk kata sandi dan nama file.

Saya punya contoh menggunakan host.ui.prompt, yang tampaknya masuk akal, tapi saya tidak bisa mengerti kembalinya.

Apakah ada cara yang lebih baik untuk mendapatkan input pengguna di PowerShell?

AJ.
sumber

Jawaban:

333

Read-Host adalah opsi sederhana untuk mendapatkan input string dari pengguna.

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

Untuk menyembunyikan kata sandi, Anda dapat menggunakan:

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

Untuk mengonversi kata sandi menjadi teks biasa:

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

Adapun jenis yang dikembalikan oleh $host.UI.Prompt(), jika Anda menjalankan kode pada tautan yang diposting di komentar @ Christian, Anda dapat mengetahui jenis pengembalian dengan memipangnya ke Get-Member(misalnya, $results | gm). Hasilnya adalah Kamus di mana kuncinya adalah nama FieldDescriptionobjek yang digunakan dalam prompt. Untuk mengakses hasilnya untuk pertama prompt dalam contoh terkait Anda akan ketik: $results['String Field'].

Untuk mengakses informasi tanpa menggunakan metode, biarkan tanda kurung mati:

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.OverloadDefinitionsakan memberi Anda definisi metode. Setiap definisi ditampilkan sebagai <Return Type> <Method Name>(<Parameters>).

Rynant
sumber
Terima kasih, @Rynant. Jawaban yang diterima sebagai satu-satunya yang benar-benar menjawab pertanyaan utama saya! ;) Semua informasi lainnya juga sangat membantu, terutama karena saya masih mencari-cari di PS.
AJ.
Tidak masalah, @AJ. Cara lain untuk mendapatkan informasi tentang suatu metode adalah dengan menghilangkan tanda kurung. Saya akan menambahkan contoh untuk jawaban saya.
Rynant
3
FYI Anda juga dapat menggunakan Get-Credential jika Anda mendapatkan nama pengguna dan kata sandi.
Matt Lyons
75

Menggunakan pengikatan parameter jelas merupakan cara untuk pergi ke sini. Tidak hanya itu sangat cepat untuk menulis (cukup tambahkan di [Parameter(Mandatory=$true)]atas parameter wajib Anda), tetapi juga satu-satunya pilihan bahwa Anda tidak akan membenci diri sendiri untuk nanti.

Lebih banyak di bawah ini:

[Console]::ReadLinesecara eksplisit dilarang oleh aturan FxCop untuk PowerShell. Mengapa? Karena hanya berfungsi di PowerShell.exe, bukan PowerShell ISE , PowerGUI , dll.

Read-Host adalah, cukup sederhana, bentuk yang buruk. Read-Host menghentikan script untuk meminta pengguna, yang berarti Anda tidak akan pernah memiliki script lain yang menyertakan script yang menggunakan Read-Host.

Anda mencoba meminta parameter.

Anda harus menggunakan [Parameter(Mandatory=$true)]atribut, dan mengoreksi pengetikan, untuk meminta parameter.

Jika Anda menggunakan ini pada [SecureString], itu akan meminta bidang kata sandi. Jika Anda menggunakan ini pada tipe Kredensial, ( [Management.Automation.PSCredential]), dialog kredensial akan muncul, jika parameter tidak ada. Sebuah string hanya akan menjadi kotak teks biasa. Jika Anda menambahkan HelpMessage ke atribut parameter (yaitu, [Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]) maka itu akan menjadi teks bantuan untuk prompt.

Mulai Otomatis
sumber
5
Ini adalah solusi yang paling fleksibel dan ramah pengguna, tetapi saya hampir mengabaikan saran Anda karena tidak ada contoh kode yang jelas seperti dalam jawaban Rynant . Bisakah Anda memberikan beberapa contoh yang diformat dengan baik?
Iain Samuel McLean Penatua
4
"Read-Host adalah, cukup sederhana, bentuk yang buruk" ... kecuali jika Anda menggunakannya untuk menerima input yang bersyarat karena seseorang tidak memanggil skrip Anda dengan parameter APA PUN. LEDAKAN.
2
Tidak: itu masih bentuk yang buruk. Itu sebabnya Anda menandai parameter sebagai wajib.
Mulai-Mengotomatisasi
2
Bagaimana jika Anda ingin menulis skrip interaktif? Katakan itu adalah skrip yang hanya membutuhkan input pengguna jika kondisi tertentu terpenuhi. Misalnya, jika skrip Anda mengatur direktori target untuk SDK, Anda mungkin ingin mengonfirmasi bahwa pengguna ingin menghapus direktori jika sudah ada.
Jason Goemaat
6
Saya pikir user1499731 memiliki poin yang bagus ... Ada kalanya Anda perlu mengambil input dari pengguna yang hanya dapat diberikan secara bermakna setelah beberapa informasi ditampilkan atau operasi lain dilakukan. Dalam hal ini, Anda tidak dapat menggunakan parameter, dan alasan yang diberikan di sini Read-Hostsebagai "bentuk buruk" tidak berlaku. Selain itu, .ShouldProcess()memiliki batasan yang Read-Hosttidak, seperti dibatasi hanya pada beberapa jawaban. Namun saya setuju itu .ShouldProcess()lebih baik, ketika itu berlaku.
LarsH
14

Tempatkan ini di bagian atas skrip Anda. Ini akan menyebabkan script meminta kata sandi kepada pengguna. Kata sandi yang dihasilkan kemudian dapat digunakan di tempat lain dalam skrip Anda melalui $ pw .

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

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

Jika Anda ingin men-debug dan melihat nilai kata sandi yang baru saja Anda baca, gunakan:

   write-host $pw
user2334160
sumber
3

Sebagai alternatif, Anda bisa menambahkannya sebagai parameter skrip untuk input sebagai bagian dari eksekusi skrip

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )
Maverick
sumber