แจ้งให้ผู้ใช้ป้อนใน PowerShell


209

ฉันต้องการให้ผู้ใช้ใส่ชุดของอินพุตรวมถึงรหัสผ่านและชื่อไฟล์

ฉันมีตัวอย่างของการใช้host.ui.promptซึ่งดูเหมือนสมเหตุสมผล แต่ฉันไม่เข้าใจการคืนสินค้า

มีวิธีที่ดีกว่าในการรับอินพุตของผู้ใช้ใน PowerShell หรือไม่

คำตอบ:


333

Read-Host เป็นตัวเลือกที่ง่ายสำหรับการรับสายเข้าจากผู้ใช้

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

ในการซ่อนรหัสผ่านคุณสามารถใช้:

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

ในการแปลงรหัสผ่านเป็นข้อความธรรมดา:

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

สำหรับประเภทที่ส่งคืนโดย$host.UI.Prompt()หากคุณเรียกใช้รหัสที่ลิงค์ที่โพสต์ในความคิดเห็นของ @ Christian คุณสามารถค้นหาประเภทที่ส่งคืนโดยการไพพ์ไปที่Get-Member(ตัวอย่างเช่น$results | gm) ผลลัพธ์คือพจนานุกรมโดยที่สำคัญคือชื่อของFieldDescriptionวัตถุที่ใช้ในพรอมต์ $results['String Field']ในการเข้าถึงผลสำหรับพรอมต์ครั้งแรกในตัวอย่างที่เชื่อมโยงคุณจะพิมพ์:

ในการเข้าถึงข้อมูลโดยไม่ต้องเรียกใช้เมธอดให้ปิดวงเล็บไว้:

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.OverloadDefinitionsจะให้คำจำกัดความของวิธีการ <Return Type> <Method Name>(<Parameters>)แต่ละคนจะแสดงความหมายเป็น


ขอบคุณ @Rynant ยอมรับคำตอบว่าเป็นคนเดียวที่ตอบคำถามหลักของฉัน! ;) ข้อมูลอื่น ๆ ทั้งหมดก็มีประโยชน์เช่นกันโดยเฉพาะอย่างยิ่งเมื่อฉันยังคงคลำทางของฉันใน PS
AJ

ไม่มีปัญหา @AJ อีกวิธีหนึ่งในการรับข้อมูลเกี่ยวกับวิธีการคือการไม่ใส่วงเล็บ ฉันจะเพิ่มตัวอย่างในคำตอบของฉัน
Rynant

3
FYI คุณสามารถใช้รับข้อมูลประจำตัวหากคุณได้รับชื่อผู้ใช้และรหัสผ่าน
Matt Lyons

75

การใช้การเชื่อมพารามิเตอร์เป็นวิธีที่จะไปที่นี่อย่างแน่นอน ไม่เพียง แต่จะรวดเร็วในการเขียน (เพียงเพิ่ม[Parameter(Mandatory=$true)]พารามิเตอร์ที่จำเป็น) แต่ยังเป็นตัวเลือกเดียวที่คุณจะไม่เกลียดตัวเองในภายหลัง

ด้านล่างเพิ่มเติม:

[Console]::ReadLineถูกห้ามอย่างชัดเจนโดยกฎFxCopสำหรับ PowerShell ทำไม? เนื่องจากใช้งานได้เฉพาะใน PowerShell.exe ไม่ใช่ PowerShell ISE , PowerGUIฯลฯ

อ่าน - โฮสต์เป็นรูปแบบที่ค่อนข้างง่าย Read-Host หยุดสคริปต์อย่างไม่สามารถควบคุมได้เพื่อแจ้งผู้ใช้ซึ่งหมายความว่าคุณจะไม่มีสคริปต์อื่นที่มีสคริปต์ที่ใช้ Read-Host

คุณกำลังพยายามขอพารามิเตอร์

คุณควรใช้[Parameter(Mandatory=$true)]คุณสมบัติและพิมพ์ที่ถูกต้องเพื่อขอพารามิเตอร์

หากคุณใช้สิ่งนี้ใน a [SecureString]จะมีข้อความแจ้งให้ใส่รหัสผ่าน หากคุณใช้สิ่งนี้กับประเภทหนังสือรับรอง ( [Management.Automation.PSCredential]) กล่องโต้ตอบข้อมูลรับรองจะปรากฏขึ้นหากพารามิเตอร์ไม่ได้อยู่ที่นั่น สตริงจะกลายเป็นกล่องข้อความธรรมดาธรรมดา หากคุณเพิ่ม HelpMessage ไปยังแอตทริบิวต์ของพารามิเตอร์ (นั่นคือ[Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]) มันจะกลายเป็นข้อความช่วยเหลือสำหรับพรอมต์


5
นี่เป็นโซลูชันที่ยืดหยุ่นและใช้งานง่ายที่สุด แต่ฉันเกือบเพิกเฉยต่อคำแนะนำของคุณเพราะไม่มีตัวอย่างรหัสที่ชัดเจนเหมือนในคำตอบของ Rynant คุณสามารถให้ตัวอย่างที่จัดรูปแบบได้ดีหรือไม่?
เลนซามูเอลแมคลีนผู้อาวุโส

4
"โฮสต์ที่อ่านแล้วเป็นเพียงรูปแบบที่ไม่ดี" ... เว้นแต่คุณจะใช้เพื่อยอมรับอินพุตที่มีเงื่อนไขที่เหลืออยู่เนื่องจากมีคนไม่ได้เรียกสคริปต์ของคุณด้วยพารามิเตอร์ใด ๆ BOOM

2
ไม่ใช่: มันยังไม่ดีนัก นั่นเป็นเหตุผลที่คุณทำเครื่องหมายพารามิเตอร์ว่าจำเป็น
เริ่มอัตโนมัติ

2
ถ้าคุณต้องการเขียนสคริปต์แบบโต้ตอบ สมมติว่าเป็นสคริปต์ที่ต้องการเพียงแค่อินพุตของผู้ใช้หากตรงตามเงื่อนไขที่กำหนด ตัวอย่างเช่นหากสคริปต์ของคุณคือการตั้งค่าไดเรกทอรีเป้าหมายสำหรับ SDK คุณอาจต้องการยืนยันว่าผู้ใช้ต้องการลบไดเรกทอรีหากมีอยู่แล้ว
Jason Goemaat

6
ฉันคิดว่า user1499731 มีจุดดี ... มีบางครั้งที่คุณจำเป็นต้องป้อนข้อมูลจากผู้ใช้ที่สามารถให้ความหมายได้หลังจากที่มีการแสดงข้อมูลหรือมีการดำเนินการอื่น ในกรณีนี้คุณไม่สามารถใช้พารามิเตอร์และเหตุผลที่ให้ไว้ที่นี่เพื่อRead-Hostใช้เป็น นอกจากนี้ยัง.ShouldProcess()มีข้อ จำกัด ที่Read-Hostไม่ได้ จำกัด อยู่เพียงแค่คำตอบเพียงไม่กี่ข้อ อย่างไรก็ตามฉันเห็นด้วยที่.ShouldProcess()ดีกว่าเมื่อมันใช้งานได้
LarsH

14

วางที่ด้านบนสุดของสคริปต์ของคุณ มันจะทำให้สคริปต์เพื่อให้ผู้ใช้รหัสผ่าน รหัสผ่านที่เกิดนั้นจะสามารถใช้ที่อื่น ๆ ในสคริปต์ของคุณผ่านทาง$ PW

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

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

หากคุณต้องการดีบักและดูค่ารหัสผ่านที่คุณเพิ่งอ่านให้ใช้:

   write-host $pw

3

คุณสามารถเพิ่มเป็นพารามิเตอร์สคริปต์สำหรับอินพุตเป็นส่วนหนึ่งของการเรียกใช้สคริปต์

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.