Question

Je crée un script Powershell pour déployer du code. Une partie du processus consiste à appeler un outil de compression de ligne de commande appelé RAR.EXE pour sauvegarder certains dossiers.

J'essaie de construire dynamiquement les paramètres, puis de faire appeler la commande PowerShell avec les variables, mais j'ai des problèmes. Ça ne marche pas ...

Exécutez le script suivant et vous devriez voir de quoi je parle. Les paramètres transmis en tant que variable sont mutilés. Si je passe toute la commande + les paramètres dans j'obtiens le fameux "n'est pas reconnu en tant qu'applet de commande ..." message.

Merci pour toute aide!

echo "this should succeed"
& cmd /c echo foo

echo "why does this echo out an additional double quote?"
$param = "/c echo foo"
& cmd "$param"

echo "this does the same"
$param = "/c echo foo"
& cmd $param

echo "escaping the slash doesn't work either..."
$param = "`/c echo foo"
& cmd $param

echo "this fails, but why?"
$cmd = "cmd /c echo foo"
&$cmd
Était-ce utile?

La solution

L'opérateur d'appel '& amp;' est inutile dans ce cas. Il est utilisé pour appeler une commande dans une nouvelle portée. Ceci est généralement utilisé pour appeler une commande spécifiée par une chaîne ou un scriptblock. En outre, toutes les variables créées dans un script PowerShell, par exemple, sont ignorées une fois la commande terminée et la portée disparue.

Cependant, étant donné que le cmd est un fichier EXE, il s'exécute dans un processus complètement différent. FWIW, vous obtenez une sortie similaire directement à partir de cmd.exe:

> cmd "/c echo foo"
foo"

La citation supplémentaire à la fin est donc un problème de cmd.exe. En règle générale, vous devez séparer la commande des paramètres lorsque PowerShell procède à l'analyse syntaxique pour appeler la commande, par exemple.

45> & { $foo = "foo" }
46> $foo  # Note that $foo wasn't found - it went away with the scope
47> . { $foo = "foo" } # dotting executes in the current scope
48> $foo 
foo

La seule exception notable est qu'Invoke-Expression se comporte comme un "évaluer cette chaîne". une fonction. Utilisez avec précaution, surtout si l’utilisateur fournit la chaîne. Votre journée pourrait être nulle si ils fournissaient "ri C: \ -r".

Dans ce cas, comme d'autres l'ont suggéré, je retirerais le / c de la chaîne $ param chaîne et le spécifierais, par exemple:

.
cmd /c $param

Ou utilisez Invoke-Expression mais utilisez avec précaution. Si vous essayez de résoudre les problèmes d’envoi d’arguments à EXE depuis PowerShell, consultez l’utilitaire echoargs dans les extensions de communauté PowerShell ( http: / /pscx.codeplex.com ). C'est très pratique:

49> $param = "/c echo foo"
50> echoargs $param
Arg 0 is </c echo foo>

Cela indique que cmd.exe reçoit " / c echo foo " en tant qu'argument unique . " / c " doit être un argument distinct de "echo foo". (la commande à exécuter).

Autres conseils

J'ai eu des problèmes avec le & amp; Dans le passé, appelez l'opérateur lorsque vous essayez d'appeler des commandes de type exécutable telles que vous les essayez. Je ne suis pas sûr de comprendre pourquoi. Invoke-Expression semble cependant toujours fonctionner dans ce contexte:

PS C:\> $cmd = "cmd /c echo foo"
PS C:\> Invoke-expression $cmd
foo

L’une des méthodes que j’ai trouvées pour cela consistait à créer un tableau d’arguments pour la ligne de commande et à l’utiliser avec apersand & amp; opérateur d'appel. Quelque chose comme ça:

$exe = "cmd";
[Array]$params = "/c", "echo", "foo";

& $exe $params;

Cela a bien fonctionné pour moi.

J'ai trouvé cette technique ici: http://techstumbler.blogspot.com/2009/12 /windows-commands-with-arguments-in.html

Votre dernier exemple en cas d'échec car " & amp; " traite la chaîne comme un argument, elle recherche donc un programme nommé "cmd / c echo foo.exe". :)

Ceci fonctionne:

& $cmd $params

En ce qui concerne le problème des guillemets doubles, il semble que cmd n’aime pas les guillemets autour des arguments proposés par PowerShell. Il obtient ceci:

cmd "/c echo foo"

Donc, je pense que tout ce qui suit / c est traité comme la commande exacte, donc, comme ceci:

echo foo"

Certains programmes en ligne de commande et l’analyse géniale de la ligne de commande (c’est pourquoi PowerShell prend en charge ce travail pour les fonctions et les applets de commande). Dans le cas de cmd, je suggérerais ceci:

$param = "echo foo"
& cmd /c $param

c’est un artefact de l’utilisation de cmd / c, je pense. en cours d'exécution

$param = "echo foo"
cmd /c $param

fonctionne bien. Sauf si vous avez un exemple de code réel, il est un peu difficile à résoudre.

Les args sont traités différemment lorsqu'ils sont contenus dans une chaîne:

PS D:\> echo "1 2 3"
1 2 3
PS D:\> echo 1 2 3
1
2
3

Les mêmes résultats se produisent lorsque vous utilisez une variable pour les arguments:

PS D:\> $param = "1 2 3"
PS D:\> echo $param
1 2 3

La solution consiste à utiliser un tableau:

PS D:\> $param = @(1,2,3)
PS D:\> echo $param
1
2
3
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top