Símbolo del sistema de Windows: ¿cómo obtengo el resultado de un comando en una variable de entorno?

59

Quiero tener una variable de entorno que contenga el día de la semana en cmd.exe.

Cuando ejecuto este comando obtengo el resultado que quiero.

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

Aquí estoy tratando de almacenar el resultado en una variable de entorno.

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

Pero cuando trato de obtenerlo, no obtengo la cadena como quería.

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

Mi objetivo es usar la variable en un archivo por lotes para algunos scripts de respaldo.

Tim
fuente

Respuestas:

87

Puedes usar algo como:

$env:DOW = "foo"
Ion Todirel
fuente
3
No entiendo por qué se marcó esto negativamente, ¿conoces una mejor para establecer variables de entorno?
Ion Todirel
2
+1 Esto funciona muy bien para mí en el escenario que necesitaba. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
David Ruhmann
14
@IonTodirel Porque esto solo persiste en el espacio del proceso.
JohnD
finalmente ahora entiendo cómo configurar RAILS_ENV en powershell
wired00
Y luego, ¿cómo lo genera para asegurarse de que funcionó?
CodyBugstein
22

Debe ejecutar ambos comandos en PowerShell ya que PowerShell es más que capaz de manipular variables ambientales.

Es decir:

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

o

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

Por cierto, su script no funciona porque todo lo que obtiene es el código de retorno de PowerShell, no los datos que produce. Puede haber una manera de hacer que funcione, pero en última instancia no tiene sentido en comparación con solo usar un script de PowerShell adecuado.

Para completar, aquí hay un buen artículo de Microsoft sobre PowerShell y variables ambientales:

Crear y modificar variables de entorno

Actualización: Después de revisar esta solución con @ syneticon-dj en el chat, parece que el problema que enfrenta al usar este método es que se debe volver a cargar un símbolo del sistema antes de que refleje los cambios en las variables ambientales que se han producido externamente.

No ha proporcionado muchos detalles sobre lo que está haciendo, pero si esta es la única razón por la que está iniciando PowerShell, mi sugerencia real sería revisar cómo está haciendo las cosas.

¿Su proceso completo usa PowerShell o ha considerado usar tareas programadas? Puede programar tareas según el día de la semana.

Dan
fuente
El archivo por lotes se ejecutará todos los días y se ejecutará desde las tareas programadas. Estoy pensando en trabajar en PowerShell en su lugar. Pero soy aún más novato en PowerShell que cmd. Y ahora estoy teniendo dificultades con un simple comando. Pero puedo hacer una nueva pregunta sobre esa, tal vez sea una pregunta fácil para usted :) EDITAR: Lo he resuelto. Era cómo ejecutar un programa con algunos parámetros.
Tim
Tampoco soy bueno en PowerShell, pero vale la pena aprenderlo. Para empezar, es mejor en casi todos los sentidos, pero también es la forma en que Microsoft (y otros fabricantes) se están moviendo.
Dan
1
Además, tenga en cuenta que la sugerencia de @ Dan anterior establece las variables de entorno de forma bastante permanente (ya sea en el contexto de la Máquina o del Usuario). Si omite el tercer parámetro, puede configurarlo solo para el proceso actual, que a veces es más deseable.
Por Lundberg
20

Creo que la variable de entorno desde dentro PowerShell con [Environment]::SetEnvironmentVariablelo sugerido por Dan no tiene sentido, ya que tendría ya sea perder el contenido de la variable a la terminación de PowerShell si elige el "proceso" contexto temporal o no lo haría en el entorno de su archivo por lotes sin embargo, si elige el contexto permanente "máquina" o "usuario", es decir, a menos que todo su script esté escrito en PowerShell, donde el problema no surgiría en primer lugar:

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>

Puede usar el forcomando como solución alternativa para analizar el resultado de su comando de PowerShell y ponerlo en una variable:

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

Tenga en cuenta los caracteres de intercalación ^utilizados para escapar de los caracteres especiales de paréntesis dentro de su llamada de PowerShell.

Si lo está probando desde la línea de comandos y no desde un contexto de archivo por lotes, deberá reemplazar las %%referencias de variables anteriores por %:

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>
el wabbit
fuente
No, esto es incorrecto. Mi ejemplo a continuación establece variables ambientales 'normales' a las que se puede acceder desde cualquier archivo por lotes, etc.
Dan
@Dan, creo que estás equivocado, he intentado configurar [Environment]::SetEnvironmentVariable("DOW", $dow, "user")desde una sesión de PowerShell en ejecución, pero no estaba presente en mi sesión de cmd principal al finalizar PowerShell
the-wabbit el
El formato lo ha estropeado, pero no ha definido $ dow. Ejecutar mi ejemplo en un script de Powershell almacena una variable de entorno normal como se esperaba.
Dan
1
@Dan BTW: No me importa el voto negativo, pero cabe señalar que el enfoque demostrado claramente hace lo que ha pedido el interrogador , por lo que incluso si hubiera un enfoque más elegante, aún sería una solución válida para el problema.
the-wabbit
1
@ the-wabbit Eso suena como un comportamiento normal en Windows. Incluso si actualiza las variables de entorno global, solo los procesos iniciados desde la actualización reconocerán el cambio. Como se trata de un proceso principal , debe haber comenzado antes del cambio. Lo mismo sucede con el SETsímbolo del sistema. Intenta comenzar un niño cmd.exey verás lo mismo. Sin embargo, el comportamiento que está viendo en PowerShell se debe a que la actualización de las variables de entorno a través de las clases .NET no afecta el proceso actual.
jpmc26
4

Si fuera yo, y el script principal tiene que ser un script de shell, simplemente haría una invocación descarada de PowerShell en el script .CMD como:

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

Es posible que deba verificar su política de ejecución de PowerShell (cmdlet Set-ExecutionPolicy).

Simon Catlin
fuente
3

O si está casado con esto en el viejo shell, omita PowerShell por completo.

Use la variable% date% y expanda el día desde la abreviatura que proporciona (esto podría verse afectado por la configuración de formato de fecha regional):

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

Tome el primer token en la respuesta y amplíe eso:

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
fuente
1
Windows 10 no mostrará el DOW en% DATE%: H: \> echo% date% 20/03/2019
Raúl Salinas-Monteagudo
1

En realidad, cuando coloca algo como lo siguiente en un archivo .ps1 (digamos t.ps1) y lo llama desde una sesión CMD con PowerShell -File t.ps1... funciona bien.

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

Pero no para la sesión CMD desde donde se ha llamado al script t.ps1. En una nueva sesión de CMD obtenemos:

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

Supongo que tenemos que descubrir cómo hacer algo como export T=dateen una sesión de CMD.

Edgar
fuente
1

Si desea que su archivo por lotes acceda a las variables de entorno establecidas por un comando de PowerShell ejecutado desde ese archivo por lotes, puede usar la siguiente solución:

Haga que su script de PowerShell cree un archivo por lotes secundario mysub.bat, que contenga líneas "set variable = value", y ejecute ese archivo por lotes mysub.bat desde el archivo por lotes principal justo después del comando PowerShell.

Utilice el método WriteAllLines en lugar de los métodos de salida predeterminados de PowerShell para que el archivo de sub lotes no se genere con el formato de codificación UTF-8.

Ejemplo

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
usuario262456
fuente