101 votes

Comment passer des arguments de ligne de commande à un fichier ps1 PowerShell ?

Pendant des années, j'ai utilisé le cmd/DOS/Windows et passer des arguments de ligne de commande aux fichiers batch. Par exemple, j'ai un fichier, zuzu.bat et dans celui-ci, j'accède %1 , %2 etc. Maintenant, je veux faire la même chose lorsque j'appelle une fonction PowerShell script when I am in a Cmd.exe shell . J'ai un script, xuxu.ps1 (et j'ai ajouté PS1 à ma variable PATHEXT et associé les fichiers PS1 avec PowerShell). Mais quoi que je fasse, je ne parviens pas à obtenir quoi que ce soit à partir de l'application $args variable. Elle a toujours une longueur de 0.

Si je suis dans un PowerShell au lieu de cmd.exe il fonctionne (bien sûr). Mais je ne suis pas encore assez à l'aise pour vivre dans l'environnement PowerShell à plein temps. Je n'ai pas envie de taper powershell.exe -command xuxu.ps1 p1 p2 p3 p4 . Je veux taper xuxu p1 p2 p3 p4 .

Est-ce possible, et si oui, comment ?

L'exemple que je n'arrive pas à faire fonctionner est trivial, foo.ps1 :

Write-Host "Num Args:" $args.Length;
foreach ($arg in $args) {
    Write-Host "Arg: $arg";
}

Les résultats sont toujours les mêmes :

C:\temp> foo
Num Args: 0
C:\temp> foo a b c d
Num Args: 0
c:\temp>

43voto

Arjun Points 767

Cet article aide. En particulier, cette section :

-Fichier

Exécute le script spécifié dans la portée locale ("dot-sourced"), de sorte que les fonctions et les variables que le script crée sont disponibles dans la session actuelle. Entrez le chemin du fichier script et les paramètres éventuels. File doit être le dernier paramètre de la commande, car tous les caractères tapés après le nom du paramètre File sont interprétés comme le chemin du fichier script suivi des paramètres script.

c'est-à-dire

powershell.exe -File "C:\myfile.ps1" arg1 arg2 arg3

signifie exécuter le fichier myfile.ps1 et arg1 arg2 & arg3 sont les paramètres pour le script de PowerShell.

1 votes

Cela n'aide toujours pas à répondre à la demande de l'opérateur ("Je veux taper xuxu p1 p2 p3 p4 ").

23voto

Randall Borck Points 217

Après avoir fouillé dans la documentation PowerShell, j'ai découvert quelques informations utiles sur ce problème. Vous ne pouvez pas utiliser l'option $args si vous avez utilisé le param(...) au début de votre fichier ; à la place vous devrez utiliser $PSBoundParameters . J'ai copié/collé votre code dans un script PowerShell, et il a fonctionné comme on pouvait s'y attendre dans la version 2 de PowerShell (je ne suis pas sûr de la version sur laquelle vous étiez lorsque vous avez rencontré ce problème).

Si vous utilisez $PSBoundParameters (et cela fonctionne UNIQUEMENT si vous utilisez l'option param(...) au début de votre script), alors ce n'est pas un tableau, c'est une table de hachage, donc vous devrez la référencer en utilisant la paire clé/valeur.

param($p1, $p2, $p3, $p4)
$Script:args=""
write-host "Num Args: " $PSBoundParameters.Keys.Count
foreach ($key in $PSBoundParameters.keys) {
    $Script:args+= "`$$key=" + $PSBoundParameters["$key"] + "  "
}
write-host $Script:args

Et quand on l'appelle avec...

PS> ./foo.ps1 a b c d

Le résultat est...

Num Args:  4
$p1=a  $p2=b  $p3=c  $p4=d

0 votes

Cela ne tient pas compte du fait que le PO commence sa ligne de commande avec powershell.exe ou pwsh. Le comportement change lorsque OP fait cela.

2 votes

@EricHansen Je ne sais pas ce que vous voulez dire, j'obtiens le même résultat dans les deux cas : ` Powershell>powershell.exe . \ParamTest.ps1 val1 val2 val3 val4 Num Args : 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4 ``.

0 votes

@RandallBrock Le comportement des arguments change pour moi. Si je suis dans CMD/batch, et que je fais quelque chose comme pwsh .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4 il n'aime vraiment pas ça. D'un autre côté, si je suis dans PowerShell et que je fais .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4 qui fonctionne comme je m'y attendais. J'ai entendu dire que c'est ainsi qu'il est censé fonctionner pour des "raisons de sécurité".

18voto

EBGreen Points 14478

OK, tout d'abord, il s'agit de casser une fonction de sécurité de base dans PowerShell. Ceci étant dit, voici comment vous pouvez le faire :

  1. Ouvrez un Explorateur Windows fenêtre
  2. Menu Outils -> Options des dossiers -> onglet Types de fichiers
  3. Trouvez le type de fichier PS1 et cliquez sur le bouton "Avancé".
  4. Cliquez sur le bouton Nouveau
  5. Pour mise en action : Ouvrir
  6. Pour l'application mise : " C:\WINNT\system32\WindowsPowerShell\v1.0\powershell.exe " "-file" "%1" %*

Vous pouvez mettre un -NoProfile en fonction de ce que fait votre profil.

4 votes

Je pense que la clé est dans votre étape 6 où vous passez les paramètres à powershell.exe. Daniel dit qu'il a associé des fichiers PS1 à PowerShell mais que cela ne permet pas de passer les arguments sans les spécifications supplémentaires %1 %*. Notez également que le paramètre -File n'est pas disponible dans la V1. Il est nouveau dans la V2.

0 votes

Bonne remarque concernant le paramètre -file, je l'avais oublié.

0 votes

Je vais devoir installer la V2 avant de pouvoir essayer votre suggestion. Merci. Lorsque vous dites que cela brise une fonction de sécurité de base, que voulez-vous dire par "cela" ? Appeler un script PowerShell depuis Cmd.exe comme s'il s'agissait d'un fichier .com/.bat/.exe ? Passer des paramètres au script ?

15voto

V.B Points 304

Vous pourriez déclarer vos paramètres dans le fichier, comme param :

[string]$para1
[string]$param2

Et ensuite, appelez le fichier PowerShell comme ceci .\temp.ps1 para1 para2....para10 etc.

6voto

guillermooo Points 2711

Peut-être que vous pouvez envelopper l'invocation PowerShell dans un fichier .bat comme suit :

rem ps.bat
@echo off
powershell.exe -command "%*"

Si vous placez ensuite ce fichier sous un dossier dans votre PATH vous pouvez appeler des scripts PowerShell comme ceci :

ps foo 1 2 3

La citation peut devenir un peu désordonnée, cependant :

ps write-host """hello from cmd!""" -foregroundcolor green

0 votes

+1 pour avoir montré les triples guillemets. ça m'a bloqué pendant un moment.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X