Wiersz polecenia systemu Windows: jak uzyskać wynik polecenia w zmiennej środowiskowej?

59

Chcę mieć zmienną środowiskową, która zawiera dzień tygodnia w cmd.exe.

Po uruchomieniu tego polecenia otrzymuję pożądany wynik.

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

Tutaj próbuję zapisać wynik w zmiennej środowiskowej.

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

Ale kiedy próbuję go zdobyć, nie otrzymuję łańcucha tak, jak chciałem.

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

Moim celem jest użycie zmiennej w pliku wsadowym dla niektórych skryptów kopii zapasowych.

Tim
źródło

Odpowiedzi:

87

Możesz użyć czegoś takiego jak:

$env:DOW = "foo"
Jon Todirel
źródło
3
Nie rozumiem, dlaczego oznaczono to negatywnie, czy wiesz o lepszym ustawianiu zmiennych środowiskowych?
Ion Todirel
2
+1 Działa to dla mnie świetnie w scenariuszu, którego potrzebowałem. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
David Ruhmann
14
@IonTodirel Ponieważ to utrzymuje się tylko w przestrzeni procesu.
JohnD
wreszcie rozumiem, jak ustawić RAILS_ENV w PowerShell
przewodowym00
A w jaki sposób wyprowadzasz go, aby upewnić się, że działa?
CodyBugstein
22

Powinieneś uruchomić oba polecenia w PowerShell, ponieważ PowerShell jest więcej niż zdolny do manipulowania zmiennymi środowiskowymi.

To znaczy:

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

lub

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

Nawiasem mówiąc, twój skrypt nie działa, ponieważ otrzymujesz tylko kod powrotu PowerShell, a nie generowane przez niego dane. Może istnieć sposób na uruchomienie go, ale jest to ostatecznie bezcelowe w porównaniu z użyciem odpowiedniego skryptu PowerShell.

Dla kompletności, oto miły artykuł od Microsoft na temat PowerShell i zmiennych środowiskowych:

Tworzenie i modyfikowanie zmiennych środowiskowych

Aktualizacja: po sprawdzeniu tego rozwiązania w @ syneticon-dj na czacie, wydaje się, że napotykasz problem przy użyciu tej metody, ponieważ wiersz polecenia musi zostać ponownie załadowany, zanim będzie odzwierciedlał zmiany zmiennych środowiskowych, które miały miejsce na zewnątrz.

Nie podałeś zbyt wielu szczegółów na temat tego, co robisz, ale jeśli jest to jedyny powód, dla którego uruchamiasz PowerShell, to moja rzeczywista sugestia sprawdzi, jak to robisz.

Albo cały proces używasz programu PowerShell, czy zamiast tego rozważasz użycie zaplanowanych zadań? Możesz planować zadania na podstawie dnia tygodnia.

Dan
źródło
Plik wsadowy będzie uruchamiany codziennie i jest uruchamiany z zaplanowanych zadań. Zamiast tego myślę o pracy w PowerShell. Ale jestem jeszcze bardziej początkującym w PowerShellem niż cmd. A teraz mam trudności z prostym poleceniem. Ale mogę zadać nowe pytanie na ten temat, może to dla ciebie łatwe :) EDYCJA: Rozgryzłem to. To było jak uruchomić program z niektórymi parametrami.
Tim
Nie jestem też świetny w PowerShell, ale warto się go nauczyć. Na początek jest po prostu lepszy pod każdym względem, ale jest to również sposób, w jaki poruszają się Microsoft (i tak inni producenci).
Dan
1
Zauważ też, że powyższa sugestia @ Dan ustawia zmienne środowiskowe dość trwale (w kontekście komputera lub użytkownika). Jeśli pominiesz trzeci parametr, możesz ustawić go tylko dla bieżącego procesu, co jest czasem bardziej pożądane.
Per Lundberg
20

Uważam, że ustawienie zmiennej środowiskowej w programie PowerShell za pomocą [Environment]::SetEnvironmentVariablesugerowanej przez Dana jest bezcelowe, ponieważ albo stracisz zawartość zmiennej po zakończeniu programu PowerShell, jeśli wybierzesz tymczasowy kontekst „procesu”, albo nie będzie go jeszcze w środowisku pliku wsadowego jeśli wybrałeś stały kontekst „komputer” lub „użytkownik” - to znaczy, chyba że cały skrypt jest napisany w PowerShell, gdzie problem nie pojawiłby się w pierwszej kolejności:

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>

Można użyć tego forpolecenia jako obejścia, aby przeanalizować dane wyjściowe polecenia PowerShell i umieścić je w zmiennej:

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

Zwróć uwagę na znaki karetki ^używane do ucieczki z nawiasów specjalnych w wywołaniu PowerShell.

Jeśli testujesz go z wiersza poleceń, a nie z kontekstu pliku wsadowego, musisz zastąpić %%odniesienia przed zmiennymi przez %:

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>
the-wabbit
źródło
Nie, to jest niepoprawne. Mój przykład poniżej ustawia „normalne” zmienne środowiskowe, które są dostępne z dowolnego pliku wsadowego itp.
Dan
@ Czy uważam, że się mylisz, próbowałem ustawienia [Environment]::SetEnvironmentVariable("DOW", $dow, "user")z uruchomionej sesji programu PowerShell, ale nie było jej w mojej nadrzędnej sesji cmd po zakończeniu programu PowerShell
the-wabbit
Formatowanie to zepsuło, ale nie zdefiniowałeś $ dow. Uruchomienie mojego przykładu w skrypcie Powershell przechowuje normalną zmienną środowiskową zgodnie z oczekiwaniami.
Dan
1
@ Dan BTW: Nie przeszkadza mi głosowanie w dół, ale należy zauważyć, że wykazane podejście wyraźnie robi to, o co pytający pytał , więc nawet gdyby było bardziej eleganckie podejście, nadal byłoby to prawidłowe rozwiązanie problemu.
the-wabbit
1
@ the-wabbit To brzmi jak normalne zachowanie w systemie Windows. Nawet jeśli zaktualizujesz globalne zmienne środowiskowe, rozpoczną się tylko procesy, ponieważ aktualizacja rozpozna zmianę. Ponieważ mówisz o procesie nadrzędnym , musiał on rozpocząć się przed zmianą. To samo dzieje się z SETwierszem polecenia. Spróbuj założyć dziecko, cmd.exea zobaczysz to samo. Zachowanie, które widzisz w PowerShell, jest jednak spowodowane tym, że aktualizacja zmiennych środowiskowych za pomocą klas .NET nie wpływa na bieżący proces.
jpmc26
4

Gdyby było mnie, a skrypt rodzic ma być skrypt, to bym po prostu zrobić bezczelny wywoływanie PowerShell w skrypcie cmd jak:

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

Może być konieczne sprawdzenie zasad wykonywania programu PowerShell (polecenie cmdlet Set-ExecutionPolicy).

Simon Catlin
źródło
3

Lub jeśli jesteś żonaty, robiąc to w starej powłoce, całkowicie pomiń PowerShell.

Użyj zmiennej% date% i rozwiń dzień ze skrótu, który daje (może to mieć wpływ na ustawienia regionalnego formatu daty):

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

Chwyć pierwszy token w odpowiedzi i rozwiń na nim:

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
Pan Jeremy Carter
źródło
1
Windows 10 nie pokaże DOW w% DATE%: H: \> echo% date% 20/03/2019
Raúl Salinas-Monteagudo
1

W rzeczywistości, umieszczając coś takiego jak poniżej w pliku .ps1 (powiedzmy t.ps1) i wywołując go z sesji CMD za pomocą PowerShell -File t.ps1... działa dobrze.

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

Ale nie w przypadku sesji CMD, z której został wywołany skrypt t.ps1. W nowej sesji CMD otrzymujemy:

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

Chyba musimy dowiedzieć się, jak zrobić coś takiego jak export T=datesesja CMD.

Edgar
źródło
1

Jeśli chcesz, aby plik wsadowy miał dostęp do zmiennych środowiskowych ustawionych za pomocą polecenia PowerShell, uruchamianego z tego pliku wsadowego, możesz zastosować następujące obejście:

Spraw, aby skrypt PowerShell utworzył plik wsadowy podrzędny mysub.bat, który zawiera wiersze „ustaw zmienną = wartość”, i uruchom ten plik wsadowy mysub.bat z głównego pliku wsadowego zaraz po poleceniu PowerShell.

Użyj metody WriteAllLines zamiast domyślnych metod wyjściowych PowerShell, aby plik wsadowy nie był generowany w formacie kodowania UTF-8.

Przykład

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
użytkownik262456
źródło