Solicitar la entrada del usuario en PowerShell

225

Quiero solicitar al usuario una serie de entradas, incluida una contraseña y un nombre de archivo.

Tengo un ejemplo de uso host.ui.prompt, que parece sensato, pero no entiendo la devolución.

¿Existe una mejor manera de obtener la entrada del usuario en PowerShell?

0
361

Read-Host es una opción simple para obtener la entrada de cadena de un usuario.

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

Para ocultar las contraseñas puede utilizar:

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

Para convertir la contraseña a texto sin formato:

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

En cuanto al tipo devuelto por $host.UI.Prompt(), si ejecuta el código en el enlace publicado en el comentario de @ Christian, puede averiguar el tipo de retorno canalizándolo a Get-Member(por ejemplo, $results | gm). El resultado es un diccionario donde la clave es el nombre de un FieldDescriptionobjeto utilizado en la solicitud. Para acceder al resultado para el primer indicador en el ejemplo enlazado debería escribir: $results['String Field'].

Para acceder a la información sin invocar un método, deje los paréntesis fuera:

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.OverloadDefinitionsle dará la (s) definición (es) del método. Cada definición se muestra como <Return Type> <Method Name>(<Parameters>).

3
  • Gracias, @Rynant. ¡Respuesta aceptada por ser el único que realmente respondió a mi pregunta principal! ;) Toda la otra información también es muy útil, especialmente porque todavía estoy buscando a tientas en PS.
    AJ.
    23/11/11 a las 12:38
  • No hay problema, @AJ. Otra forma de obtener información sobre un método es dejar los paréntesis. Agregaré un ejemplo a mi respuesta.
    Rynant
    23/11/11 a las 14:09
  • 3
    Para su información, también puede usar Get-Credential si obtiene nombres de usuario y contraseñas. 3 feb 2015 a las 4:07
76

El uso de la vinculación de parámetros es definitivamente el camino a seguir aquí. No solo es muy rápido de escribir (solo agregue por [Parameter(Mandatory=$true)]encima de sus parámetros obligatorios), sino que también es la única opción por la que no se odiará más adelante.

Más abajo:

[Console]::ReadLineestá explícitamente prohibido por las reglas de FxCop para PowerShell. ¿Por qué? Porque solo funciona en PowerShell.exe, no en PowerShell ISE , PowerGUI , etc.

Read-Host es, simplemente, de mala forma. Read-Host detiene incontrolablemente la secuencia de comandos para solicitar al usuario, lo que significa que nunca podrá tener otra secuencia de comandos que incluya la secuencia de comandos que utiliza Read-Host.

Estás intentando solicitar parámetros.

Debe utilizar el [Parameter(Mandatory=$true)]atributo y escribir correctamente para solicitar los parámetros.

Si usa esto en un [SecureString], le pedirá un campo de contraseña. Si usa esto en un tipo de credencial, ( [Management.Automation.PSCredential]), aparecerá el cuadro de diálogo de credenciales, si el parámetro no está allí. Una cadena se convertirá en un simple cuadro de texto antiguo. Si agrega un HelpMessage al atributo del parámetro (es decir, [Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]), se convertirá en texto de ayuda para el mensaje.

8
  • 6
    Esta es la solución más flexible y fácil de usar, pero casi ignoré su consejo porque no había ejemplos de código claros como en la respuesta de Rynant . ¿Puede proporcionar algunos ejemplos bien formateados? 22/10/2013 a las 15:31
  • 4
    "Read-Host es, simplemente, de mala forma" ... a menos que lo esté usando para aceptar condicionalmente la entrada que se dejó fuera porque alguien no estaba llamando a su script con NINGÚN parámetro. AUGE.
    user1499731
    26/08/14 a las 18:41
  • 2
    No: todavía está en mal estado. Por eso marca los parámetros como obligatorios. 2 de septiembre de 2014 a las 21:03
  • 2
    ¿Qué pasa si quieres escribir un guión interactivo? Digamos que es un script que solo requiere la entrada del usuario si se cumplen ciertas condiciones. Por ejemplo, si su secuencia de comandos es para configurar un directorio de destino para un SDK, es posible que desee confirmar que el usuario desea eliminar el directorio si ya existe. 9 de marzo de 2015 a las 6:11
  • 6
    Creo que user1499731 tuvo un buen punto ... Hay ocasiones en las que necesita recibir información del usuario que solo se puede proporcionar de manera significativa después de que se muestre alguna información o se realice otra operación. En ese caso, no puede usar un parámetro, y las razones dadas aquí para Read-Hostser de "mala forma" no se aplican. Además, .ShouldProcess()tiene restricciones que Read-Hostno las tiene, como limitarse a unas pocas respuestas. Sin embargo, estoy de acuerdo en que .ShouldProcess()es mejor, cuando sea aplicable.
    LarsH
    19/02/2016 a las 11:40
14

Coloque esto en la parte superior de su guión. Hará que la secuencia de comandos solicite al usuario una contraseña. La contraseña resultante se puede usar en cualquier otro lugar de su secuencia de comandos a través de $ pw .

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

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

Si desea depurar y ver el valor de la contraseña que acaba de leer, use:

   write-host $pw
0
3

Como alternativa, puede agregarlo como un parámetro de secuencia de comandos para la entrada como parte de la ejecución de la secuencia de comandos

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