Demander une entrée utilisateur dans PowerShell

209

Je veux demander à l'utilisateur une série d'entrées, y compris un mot de passe et un nom de fichier.

J'ai un exemple d'utilisation host.ui.prompt, qui semble raisonnable, mais je ne comprends pas le retour.

Existe-t-il un meilleur moyen d'obtenir les entrées des utilisateurs dans PowerShell?

UN J.
la source

Réponses:

333

Read-Host est une option simple pour obtenir une entrée de chaîne d'un utilisateur.

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

Pour masquer les mots de passe, vous pouvez utiliser:

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

Pour convertir le mot de passe en texte brut:

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

En ce qui concerne le type retourné par $host.UI.Prompt(), si vous exécutez le code sur le lien publié dans le commentaire de @ Christian, vous pouvez trouver le type de retour en le redirigeant vers Get-Member(par exemple, $results | gm). Le résultat est un dictionnaire où la clé est le nom d'un FieldDescriptionobjet utilisé dans l'invite. Pour accéder au résultat pour la première invite dans l'exemple lié vous tapez: $results['String Field'].

Pour accéder aux informations sans invoquer de méthode, laissez les parenthèses désactivées:

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.OverloadDefinitionsvous donnera la ou les définitions de la méthode. Chaque définition s'affiche sous la forme <Return Type> <Method Name>(<Parameters>).

Rynant
la source
Merci, @Rynant. Réponse acceptée pour être le seul à avoir répondu à ma question principale! ;) Toutes les autres informations sont également très utiles, d'autant plus que je tâtonne toujours sur PS.
AJ.
Pas de problème, @AJ. Une autre façon d'obtenir des informations sur une méthode consiste à laisser les parenthèses. J'ajouterai un exemple à ma réponse.
Rynant
3
Pour info, vous pouvez également utiliser Get-Credential si vous obtenez des noms d'utilisateur et des mots de passe.
Matt Lyons
75

L'utilisation de la liaison de paramètres est certainement la voie à suivre. Non seulement il est très rapide à écrire (ajoutez simplement [Parameter(Mandatory=$true)]au-dessus de vos paramètres obligatoires), mais c'est aussi la seule option pour laquelle vous ne vous détesterez pas plus tard.

Plus ci-dessous:

[Console]::ReadLineest explicitement interdit par les règles FxCop pour PowerShell. Pourquoi? Parce que cela ne fonctionne que dans PowerShell.exe, pas PowerShell ISE , PowerGUI , etc.

Read-Host est, tout simplement, une mauvaise forme. Read-Host arrête de façon incontrôlable le script pour inviter l'utilisateur, ce qui signifie que vous ne pouvez jamais avoir un autre script qui inclut le script qui utilise Read-Host.

Vous essayez de demander des paramètres.

Vous devez utiliser l' [Parameter(Mandatory=$true)]attribut et le typage correct pour demander les paramètres.

Si vous l'utilisez sur un [SecureString], il vous demandera un champ de mot de passe. Si vous l'utilisez sur un type d'informations d'identification, ( [Management.Automation.PSCredential]), la boîte de dialogue d'informations d'identification s'affiche si le paramètre n'est pas là. Une chaîne deviendra simplement une ancienne zone de texte ordinaire. Si vous ajoutez un HelpMessage à l'attribut de paramètre (c'est-à-dire [Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]) , il deviendra un texte d'aide pour l'invite.

Démarrage-automatisation
la source
5
C'est la solution la plus flexible et la plus conviviale, mais j'ai presque ignoré vos conseils car il n'y avait pas d'exemples de code clairs comme dans la réponse de Rynant . Pouvez-vous fournir des exemples bien formatés?
Iain Samuel McLean Elder
4
"Read-Host est, tout simplement, une mauvaise forme" ... à moins que vous ne l'utilisiez pour accepter conditionnellement une entrée qui a été omise parce que quelqu'un n'appelait pas votre script avec TOUT paramètre. BOOM.
2
Non: c'est encore une mauvaise forme alors. C'est pourquoi vous marquez les paramètres comme obligatoires.
Début d'automatisation du
2
Et si vous voulez écrire un script interactif? Supposons qu'il s'agit d'un script qui ne nécessite une entrée utilisateur que si certaines conditions sont remplies. Par exemple, si votre script doit configurer un répertoire cible pour un SDK, vous souhaiterez peut-être confirmer que l'utilisateur souhaite supprimer le répertoire s'il existe déjà.
Jason Goemaat
6
Je pense que user1499731 avait un bon point ... Il y a des moments où vous devez prendre des informations de l'utilisateur qui ne peuvent être fournies de manière significative qu'une fois que certaines informations sont affichées ou qu'une autre opération est effectuée. Dans ce cas, vous ne pouvez pas utiliser de paramètre, et les raisons données ici pour Read-Hostêtre "de mauvaise forme" ne s'appliquent pas. De plus, .ShouldProcess()a des restrictions qui Read-Hostne le font pas, comme se limiter à quelques réponses. Cependant, je conviens que .ShouldProcess()c'est mieux, quand c'est applicable.
LarsH
14

Placez-le en haut de votre script. Cela amènera le script à inviter l'utilisateur à saisir un mot de passe. Le mot de passe résultant peut ensuite être utilisé ailleurs dans votre script via $ pw .

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

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

Si vous souhaitez déboguer et voir la valeur du mot de passe que vous venez de lire, utilisez:

   write-host $pw
user2334160
la source
3

Comme alternative, vous pouvez l'ajouter en tant que paramètre de script pour l'entrée dans le cadre de l'exécution du script

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