Invite de commande Windows: comment obtenir le résultat d'une commande dans une variable d'environnement?

59

Je veux avoir une variable d'environnement qui contient le jour de la semaine dans cmd.exe.

Lorsque j'exécute cette commande, j'obtiens le résultat souhaité.

C:\Users\tisc> powershell (get-date).dayofweek
Friday

Ici, j'essaie de stocker le résultat dans une variable d'environnement.

C:\Users\tisc> set dow = powershell (get-date).dayofweek

Mais quand j'essaie de l'obtenir, je ne reçois pas la ficelle comme je le voulais.

C:\Users\tisc> set dow
DoW=0
dow = powershell (get-date).dayofweek

Mon objectif est d’utiliser la variable dans un fichier de commandes pour certains scripts de sauvegarde.

Tim
la source

Réponses:

87

Vous pouvez utiliser quelque chose comme:

$env:DOW = "foo"
Ion Todirel
la source
3
Je ne comprends pas pourquoi cela a été signalé négativement. Connaissez-vous une meilleure méthode pour définir les variables d'environnement?
Ion Todirel
2
+1 Cela fonctionne très bien pour moi dans le scénario dont j'avais besoin. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
David Ruhmann
14
@IonTodirel Parce que cela ne persiste que dans l'espace processus.
JohnD
Enfin, je comprends maintenant comment définir RAILS_ENV dans powershell
wired00
Et ensuite, comment le sortez-vous pour vous assurer qu'il fonctionne?
CodyBugstein
22

Vous devez exécuter les deux commandes dans PowerShell, car PowerShell est plus que capable de manipuler des variables d'environnement.

C'est à dire:

$dow = (get-date).dayofweek
[Environment]::SetEnvironmentVariable("DOW", $dow, "Machine")

ou

[Environment]::SetEnvironmentVariable("DOW", $dow, "User")

En passant, votre script ne fonctionne pas car tout ce que vous obtenez est le code de retour PowerShell, pas les données qu'il génère. Il y a peut-être un moyen de le faire fonctionner, mais c'est finalement inutile par rapport à un simple script PowerShell.

Pour être complet, voici un bel article de Microsoft sur PowerShell et les variables environnementales:

Création et modification de variables d'environnement

Mise à jour: après avoir examiné cette solution avec @ syneticon-dj dans le chat, il semble que le problème que vous rencontrez avec cette méthode est qu'une invite de commande doit être rechargée avant de refléter les modifications des variables d'environnement qui se sont produites en externe.

Vous n'avez pas fourni beaucoup de détails sur ce que vous faites, mais si c'est la seule raison pour laquelle vous lancez PowerShell, alors je vous suggère de revoir votre façon de faire.

Votre processus entier utilise-t-il PowerShell ou avez-vous envisagé d'utiliser des tâches planifiées à la place? Vous pouvez planifier des tâches en fonction du jour de la semaine.

Dan
la source
Le fichier de commandes sera exécuté tous les jours et est exécuté à partir des tâches planifiées. Je pense plutôt à travailler dans PowerShell. Mais je suis encore plus novice dans powershell que cmd. Et maintenant, j'ai des difficultés avec une commande simple. Mais je peux poser une nouvelle question à ce sujet, peut-être que c'est une question facile pour vous :) EDIT: Je l'ai compris. C'était comment exécuter un programme avec certains paramètres.
Tim
Je ne suis pas très bon chez PowerShell non plus, mais ça vaut la peine d'apprendre. Pour commencer, il est simplement préférable à presque tous les égards, mais c'est aussi la façon dont Microsoft (et les autres fabricants) évolue.
Dan
1
Notez également que la suggestion de @ Dan ci-dessus définit les variables d'environnement de manière assez permanente (dans le contexte Machine ou User). Si vous omettez le troisième paramètre, vous pouvez le définir uniquement pour le processus en cours, ce qui est parfois plus souhaitable.
Per Lundberg
20

Je pense qu'il [Environment]::SetEnvironmentVariableest inutile de définir la variable d'environnement à partir de PowerShell, comme suggéré par Dan, car vous perdriez le contenu de la variable à la fin de PowerShell si vous choisissiez le contexte "processus" temporaire ou ne l'aviez pas encore dans l'environnement de votre fichier de traitement par lots . si vous avez choisi le contexte permanent "machine" ou "utilisateur" - c'est-à-dire, sauf si votre script est entièrement écrit dans PowerShell, le problème ne se posant pas en premier lieu:

C:\Users\myuser> echo %DOW%
%DOW%

C:\Users\myuser> powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. Alle Rechte vorbehalten.

PS C:\Users\myuser> $dow = (get-date).dayofweek
PS C:\Users\myuser> [Environment]::SetEnvironmentVariable("DOW", $dow, "User")
PS C:\Users\myuser> [Environment]::SetEnvironmentVariable("DOW", $dow, "Process")
PS C:\Users\myuser> exit

C:\Users\myuser> echo %DOW%
%DOW%

C:\Users\myuser>

Vous pouvez utiliser la forcommande comme solution de contournement pour analyser le résultat de votre commande PowerShell et le placer dans une variable:

  for /F "usebackq tokens=1" %%i in (`powershell ^(get-date^).dayofweek`) do set DOW=%%i

Notez les caractères d'insertion ^utilisés pour échapper les caractères spéciaux entre parenthèses dans votre appel PowerShell.

Si vous le testez à partir de la ligne de commande et non à partir d'un contexte de fichier de commandes, vous devrez remplacer les %%références de variable précédentes par %:

C:\Users\myuser> for /F "usebackq tokens=1" %i in (`powershell ^(get-date^).dayofw
eek`) do set DOW=%i

C:\Users\myuser> set DOW=Friday

C:\Users\myuser>
le-wabbit
la source
Non, c'est inexact. Mon exemple ci-dessous définit les variables d'environnement 'normales' qui sont accessibles à partir de n'importe quel fichier de commandes, etc.
Dan
@ Dan Je crois que vous vous trompez, j'ai essayé de définir [Environment]::SetEnvironmentVariable("DOW", $dow, "user")une session dans une session PowerShell en cours, mais celle-ci n'était pas présente dans la session de ma commande parent à la fin de PowerShell
the-wabbit
Le formatage a tout gâché, mais vous n’avez pas défini $ dow. L'exécution de mon exemple dans un script Powershell stocke une variable d'environnement normale comme prévu.
Dan
1
@Dan BTW: Le vote négatif ne me dérange pas, mais il convient de noter que l'approche démontrée correspond clairement à ce que le questionneur a demandé . Ainsi, même si l'approche était plus élégante, ce serait toujours une solution valable au problème.
le-wabbit
1
@ the-wabbit Cela ressemble à un comportement normal sous Windows. Même si vous mettez à jour les variables d'environnement globales, seuls les processus démarrés depuis la mise à jour reconnaîtront le changement. Puisque vous parlez d'un processus parent , il doit avoir commencé avant le changement. La même chose se produit avec SETdans l'invite de commande. Essayez de démarrer un enfant cmd.exeet vous verrez la même chose. Cependant, le comportement observé dans PowerShell est dû au fait que la mise à jour des variables d'environnement via les classes .NET n'affecte pas le processus en cours.
jpmc26
4

Si elle était moi, et le script parent doit être un script shell, je venais de faire une invocation insolente de PowerShell dans le script .CMD comme:

set DOW=
for /f %%D in ('%SystemRoot%\System32\WindowsPowerShell\V1.0\powershell.exe -NoLogo -NoProfile -Command Write-Host -Object ^(Get-Date^).DayOfWeek;') do set DOW=%%D

Vous devrez peut-être vérifier votre stratégie d'exécution de PowerShell (cmdlet Set-ExecutionPolicy).

Simon Catlin
la source
3

Ou si vous êtes marié à faire cela dans l'ancienne coquille, ignorez complètement PowerShell.

Utilisez la variable% date% et développez le jour à partir de l’abréviation qu’il donne (ceci pourrait être affecté par les paramètres de format de date régionaux):

C:\> echo %date%
Thu 09/05/2013

Saisissez le premier jeton dans la réponse et développez-le:

C:\> type dayofweek.cmd
@echo off
for /f %%A in ("%date%") do set DAYOFWEEK=%%A
if "%DAYOFWEEK%" == "Mon" set DAYOFWEEK=Monday
if "%DAYOFWEEK%" == "Tue" set DAYOFWEEK=Tuesday
if "%DAYOFWEEK%" == "Wed" set DAYOFWEEK=Wednesday
if "%DAYOFWEEK%" == "Thu" set DAYOFWEEK=Thursday
if "%DAYOFWEEK%" == "Fri" set DAYOFWEEK=Friday
if "%DAYOFWEEK%" == "Sat" set DAYOFWEEK=Saturday
if "%DAYOFWEEK%" == "Sun" set DAYOFWEEK=Sunday
echo.%DAYOFWEEK%
C:\>
C:\> dayofweek
Thursday
M Jeremy Carter
la source
1
Windows 10 ne montrera pas le DOW dans% DATE%: H: \> echo% date% 20/03/2019
Raúl Salinas-Monteagudo Le
1

En fait, lorsque vous insérez quelque chose comme celui-ci dans un fichier .ps1 (par exemple, t.ps1) et que vous l'appelez à partir d'une session CMD avec PowerShell -File t.ps1... cela fonctionne bien.

$DateAndTime = (get-date -UFormat "%Y%m%d_%H%M%S")[Environment]::SetEnvironmentVariable("DateAndTime", $DateAndTime, "Machine")

Mais pas pour la session CMD où le script t.ps1 a été appelé. Dans une nouvelle session CMD, nous obtenons:

D:> echo% DateAndTime% ==> 20120208_123106

Je suppose que nous devons trouver comment faire quelque chose comme export T=datedans une session CMD.

Edgar
la source
1

Si vous souhaitez que votre fichier de commandes accède aux variables d'environnement définies par une commande PowerShell exécutées à partir de ce fichier de commandes, vous pouvez utiliser la solution de contournement suivante:

Demandez à votre script PowerShell de créer un sous-fichier de commandes, mysub.batcontenant les lignes "set variable = value", puis exécutez ce fichier de commandes mysub.bat à partir du fichier de commandes principal juste après la commande PowerShell.

Utilisez la méthode WriteAllLines plutôt que les méthodes de sortie par défaut de PowerShell afin que le fichier de sous-traitement ne soit pas généré avec le format de codage UTF-8.

Exemple

main.bat:

REM main.bat first line
powershell -Command "[System.IO.File]::WriteAllLines(\".\mysub.bat\", \"set VARIABLE=VALUE\");"
.\mysub.bat
echo VARIABLE=%VARIABLE%
REM expected output: VARIABLE=VALUE
utilisateur262456
la source