Windows-Eingabeaufforderung: Wie erhalte ich die Ausgabe eines Befehls in eine Umgebungsvariable?

59

Ich möchte eine Umgebungsvariable haben, die den Wochentag in cmd.exe enthält.

Wenn ich diesen Befehl ausführe, erhalte ich das gewünschte Ergebnis.

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

Hier versuche ich das Ergebnis in einer Umgebungsvariablen zu speichern.

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

Aber wenn ich versuche, es zu bekommen, bekomme ich nicht die Zeichenfolge, wie ich wollte.

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

Mein Ziel ist es, die Variable in einer Batch-Datei für einige Backup-Skripte zu verwenden.

Tim
quelle

Antworten:

87

Sie können Folgendes verwenden:

$env:DOW = "foo"
Ion Todirel
quelle
3
Ich verstehe nicht, warum dies negativ markiert wurde. Kennen Sie ein besseres Verfahren zum Festlegen von Umgebungsvariablen?
Ion Todirel
2
+1 Das funktioniert in dem von mir benötigten Szenario hervorragend. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
David Ruhmann
14
@IonTodirel Da dies nur im Prozessbereich besteht.
JohnD
Endlich verstehe ich, wie man RAILS_ENV in Powershell
Wired00
Und wie geben Sie es dann aus, um sicherzustellen, dass es funktioniert?
CodyBugstein
22

Sie sollten beide Befehle in PowerShell ausführen, da PowerShell Umgebungsvariablen mehr als manipulieren kann.

Dh:

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

oder

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

Ihr Skript funktioniert übrigens nicht, da Sie nur den PowerShell-Rückkehrcode und nicht die von ihm erzeugten Daten erhalten. Es kann eine Möglichkeit geben, es zum Laufen zu bringen, aber letztendlich ist es sinnlos, nur ein richtiges PowerShell-Skript zu verwenden.

Der Vollständigkeit halber ist hier ein netter Artikel von Microsoft zu PowerShell und Umgebungsvariablen:

Umgebungsvariablen erstellen und ändern

Update: Nachdem Sie diese Lösung mit @ syneticon-dj im Chat überprüft haben, besteht das Problem, das bei dieser Methode auftritt, darin, dass eine Eingabeaufforderung neu geladen werden muss, bevor Änderungen an Umgebungsvariablen berücksichtigt werden, die extern aufgetreten sind.

Sie haben nicht viele Details zu dem, was Sie gerade tun, angegeben, aber wenn dies der einzige Grund ist, warum Sie PowerShell starten, würde ich Ihnen vorschlagen, zu überprüfen, wie Sie vorgehen.

Verwenden Sie entweder PowerShell für Ihren gesamten Prozess, oder möchten Sie stattdessen geplante Aufgaben ausführen? Sie können Aufgaben basierend auf dem Wochentag planen.

Dan
quelle
Die Batchdatei wird jeden Tag ausgeführt und von den geplanten Tasks ausgeführt. Ich denke stattdessen daran, in Powershell zu arbeiten. Aber ich bin noch mehr Neuling in Powershell als Cmd. Und im Moment habe ich Schwierigkeiten mit einem einfachen Befehl. Aber ich kann eine neue Frage dazu stellen, vielleicht ist das eine leichte Frage für dich :) EDIT: Ich habe es herausgefunden. Es war, wie man ein Programm mit einigen Parametern ausführt.
Tim
Ich bin auch nicht besonders gut in PowerShell, aber es lohnt sich zu lernen. Zunächst ist es in fast jeder Hinsicht besser, aber es ist auch die Art und Weise, wie sich Microsoft (und damit auch andere Hersteller) bewegen.
Dan
1
Beachten Sie auch, dass der obige @ Dan-Vorschlag die Umgebungsvariablen ziemlich permanent festlegt (entweder im Maschinen- oder im Benutzerkontext). Wenn Sie den dritten Parameter weglassen, können Sie ihn nur für den aktuellen Prozess festlegen, was manchmal wünschenswerter ist.
Per Lundberg
20

Ich glaube , die Einstellung den Umgebungsvariable aus Powershell mit [Environment]::SetEnvironmentVariablewie von Dan vorgeschlagen ist sinnlos, da würden Sie entweder der Inhalt nach Beendigung der Powershell des Variable verlieren , wenn Sie den temporären „Prozess“ Kontext wählen oder wäre es nicht in der Batch - Datei der Umwelt haben noch Wenn Sie den permanenten "Computer" - oder "Benutzer" -Kontext gewählt haben, dh wenn Ihr gesamtes Skript nicht in PowerShell geschrieben ist, tritt das Problem nicht an erster Stelle auf:

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>

Sie können den forBefehl als Problemumgehung verwenden, um die Ausgabe Ihres PowerShell-Befehls zu analysieren und in eine Variable einzufügen:

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

Beachten Sie die Caret-Zeichen, die ^verwendet werden, um die Sonderzeichen in Klammern in Ihrem PowerShell-Aufruf zu maskieren.

Wenn Sie es von der Befehlszeile aus und nicht aus einem Batch-Dateikontext heraus testen, müssen Sie die %%Verweise auf die Before-Variablen ersetzen durch %:

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>
das-wabbit
quelle
Nein, das ist falsch. In meinem folgenden Beispiel werden 'normale' Umgebungsvariablen festgelegt, auf die von jeder Batchdatei usw. zugegriffen werden kann.
Dan
@Dan Ich glaube, Sie haben sich geirrt. Ich habe versucht, die Einstellung [Environment]::SetEnvironmentVariable("DOW", $dow, "user")innerhalb einer laufenden Powershell-Sitzung vorzunehmen, aber sie war bei der Beendigung von PowerShell
the-wabbit am
Die Formatierung hat das vermasselt, aber Sie haben $ dow nicht definiert. Das Ausführen meines Beispiels in einem Powershell-Skript speichert erwartungsgemäß eine normale Umgebungsvariable.
Dan
1
@Dan BTW: Ich habe nichts gegen das Downvoting, aber es sollte beachtet werden, dass der demonstrierte Ansatz klar das tut, was der Fragesteller verlangt hat. Selbst wenn es einen eleganteren Ansatz gäbe, wäre er dennoch eine gültige Lösung für das Problem.
the-wabbit
1
@ the-wabbit Das klingt nach normalem Verhalten in Windows. Selbst wenn Sie die globalen Umgebungsvariablen aktualisieren, wird die Änderung nur von Prozessen erkannt, die seit der Aktualisierung gestartet wurden . Da es sich um einen übergeordneten Prozess handelt, muss dieser vor der Änderung gestartet worden sein. Das gleiche passiert SETin der Eingabeaufforderung. Wenn cmd.exeSie versuchen, ein Kind zu gründen, sehen Sie dasselbe. Das Verhalten in PowerShell ist jedoch darauf zurückzuführen, dass das Aktualisieren der Umgebungsvariablen über die .NET-Klassen keinen Einfluss auf den aktuellen Prozess hat.
jpmc26
4

Wenn es nach mir ginge, und das übergeordnete Skript hat einen Shell - Skript sein, würde ich nur einen frechen Aufruf von Powershell in der .CMD Skript wie:

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

Möglicherweise müssen Sie Ihre PowerShell-Ausführungsrichtlinie (Cmdlet Set-ExecutionPolicy) überprüfen.

Simon Catlin
quelle
3

Wenn Sie dazu in der alten Shell verheiratet sind, überspringen Sie PowerShell vollständig.

Verwenden Sie die Variable% date% und erweitern Sie den Tag anhand der angegebenen Abkürzung (dies kann durch regionale Datumsformateinstellungen beeinflusst werden):

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

Nimm das erste Token in der Antwort und erweitere es:

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
quelle
1
Windows 10 zeigt den DOW nicht in% DATE%: H: \> echo% date% 20/03/2019
Raúl Salinas-Monteagudo,
1

Eigentlich funktioniert es gut , wenn man so etwas wie das Folgende in eine .ps1-Datei schreibt (sagen wir t.ps1) und es aus einer CMD-Sitzung mit PowerShell aufruft -File t.ps1.

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

Aber nicht für die CMD-Sitzung, von der aus das Skript t.ps1 aufgerufen wurde. In einer neuen CMD-Sitzung erhalten wir:

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

Ich denke, wir müssen herausfinden, wie man so etwas wie export T=datein einer CMD-Sitzung macht.

Edgar
quelle
1

Wenn Sie möchten, dass Ihre Batchdatei auf Umgebungsvariablen zugreift, die mit einem PowerShell-Befehl festgelegt wurden, der über diese Batchdatei ausgeführt wird, können Sie die folgende Problemumgehung verwenden:

Erstellen Sie mit Ihrem PowerShell-Skript eine Sub-Batch-Datei mit den mysub.batZeilen "set variable = value" und führen Sie die Batch-Datei mysub.bat direkt nach dem PowerShell-Befehl aus der Haupt-Batch-Datei aus.

Verwenden Sie die WriteAllLines-Methode anstelle der Standard-PowerShell-Ausgabemethoden, damit die Sub-Batch-Datei nicht mit dem UTF-8-Codierungsformat generiert wird.

Beispiel

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
user262456
quelle