Dấu nhắc lệnh của Windows: làm cách nào để đưa đầu ra của lệnh vào biến môi trường?


59

Tôi muốn có một biến môi trường chứa ngày trong tuần trong cmd.exe.

Khi tôi chạy lệnh này, tôi nhận được kết quả tôi muốn.

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

Ở đây tôi đang cố gắng lưu trữ kết quả trong một biến môi trường.

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

Nhưng khi tôi cố gắng để có được nó, tôi không nhận được chuỗi như tôi muốn.

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

Mục tiêu của tôi là sử dụng biến trong một tệp bó cho một số tập lệnh sao lưu.

Câu trả lời:


87

Bạn có thể sử dụng một cái gì đó như:

$env:DOW = "foo"

3
Tôi không hiểu tại sao điều này được gắn cờ tiêu cực, bạn có biết cách tốt hơn để đặt các biến môi trường không?
Ion Todirel

2
+1 Điều này hoạt động rất tốt cho tôi trong kịch bản tôi cần. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
David Ruhmann

14
@IonTodirel Bởi vì điều này chỉ tồn tại trong không gian quá trình.
JohnD

cuối cùng bây giờ tôi đã hiểu làm thế nào để thiết lập RAILS_ENV trong powershell
Wired00

Và sau đó làm thế nào để bạn xuất nó để đảm bảo nó hoạt động?
CodyBugstein ngày

22

Bạn nên chạy cả hai lệnh trong PowerShell vì PowerShell không chỉ có khả năng thao túng các biến môi trường.

I E:

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

hoặc là

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

Nhân tiện, tập lệnh của bạn không hoạt động vì tất cả những gì bạn nhận được là mã trả về PowerShell, không phải dữ liệu mà nó tạo ra. Có thể có một cách để làm cho nó hoạt động, nhưng cuối cùng nó là vô nghĩa so với việc chỉ sử dụng một tập lệnh PowerShell thích hợp.

Để hoàn thiện, đây là một bài viết hay của Microsoft về PowerShell và các biến môi trường:

Tạo và sửa đổi biến môi trường

Cập nhật: Đã xem xét giải pháp này với @ syirecton-dj trong trò chuyện, có vẻ như vấn đề bạn gặp phải khi sử dụng phương pháp này là một dấu nhắc lệnh phải được tải lại trước khi nó phản ánh các thay đổi trong các biến môi trường đã xảy ra bên ngoài.

Bạn chưa cung cấp nhiều chi tiết về những gì bạn đang làm, nhưng nếu đây là lý do duy nhất bạn khởi chạy PowerShell, thì đề xuất thực tế của tôi sẽ xem xét cách bạn đang làm.

Toàn bộ quá trình của bạn sử dụng PowerShell hoặc bạn đã xem xét sử dụng các tác vụ theo lịch trình thay thế chưa? Bạn có thể lên lịch các nhiệm vụ dựa trên ngày trong tuần.


Tệp bó sẽ được chạy mỗi ngày và được chạy từ các tác vụ theo lịch trình. Tôi nghĩ rằng làm việc trong powershell thay thế. Nhưng tôi thậm chí còn nhiều người mới trong powershell hơn cmd. Và ngay bây giờ tôi gặp khó khăn với một lệnh đơn giản. Nhưng tôi có thể đưa ra một câu hỏi mới về câu hỏi đó, có thể đó là một câu hỏi dễ cho bạn :) EDIT: Tôi đã tìm ra nó. Đó là cách chạy một chương trình với một số tham số.
Tim

Tôi cũng không giỏi về PowerShell, nhưng nó cũng đáng để học hỏi. Để bắt đầu, nó chỉ tốt hơn về mọi mặt, nhưng đó cũng là cách Microsoft (Và vì vậy các nhà sản xuất khác) đang di chuyển.
Dan

1
Ngoài ra, lưu ý rằng đề xuất của @ Dan ở trên đặt các biến môi trường khá lâu dài (trong bối cảnh Máy hoặc Người dùng). Nếu bạn bỏ qua tham số thứ ba, bạn có thể đặt nó cho quy trình hiện tại, điều này đôi khi được mong muốn hơn.
Per Lundberg

20

Tôi tin rằng thiết lập các biến môi trường từ bên trong PowerShell với [Environment]::SetEnvironmentVariabletheo đề nghị của Dan là vô nghĩa, bởi vì bạn sẽ hoặc là mất nội dung của biến khi chấm dứt PowerShell nếu bạn chọn tạm thời "quy trình" bối cảnh hoặc sẽ không có nó trong môi trường tập tin thực thi của bạn chưa nếu bạn chọn bối cảnh "máy" hoặc "người dùng" vĩnh viễn - nghĩa là, trừ khi toàn bộ tập lệnh của bạn được viết bằng PowerShell, nơi mà vấn đề sẽ không phát sinh ở nơi đầu tiên:

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>

Bạn có thể sử dụng forlệnh như một cách giải quyết để phân tích đầu ra của lệnh PowerShell và đặt nó vào một biến:

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

Lưu ý các ký tự dấu mũ ^được sử dụng để thoát các ký tự đặc biệt trong ngoặc đơn trong cuộc gọi PowerShell của bạn.

Nếu bạn đang kiểm tra nó từ dòng lệnh chứ không phải trong bối cảnh tệp bó, bạn sẽ cần thay thế các %%tham chiếu trước khi biến bằng cách %:

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>

Không, điều này không chính xác. Ví dụ của tôi dưới đây đặt các biến môi trường 'bình thường' có thể truy cập được từ bất kỳ tệp bó nào, v.v.
Dan

@ Tôi có thể tin rằng bạn đã nhầm, tôi đã thử cài đặt [Environment]::SetEnvironmentVariable("DOW", $dow, "user")trong một phiên quyền hạn đang chạy nhưng nó không có trong phiên cmd của cha mẹ tôi khi chấm dứt PowerShell
the-wợi

Định dạng đã làm hỏng nó lên, nhưng bạn chưa xác định $ dow. Chạy ví dụ của tôi trong tập lệnh Powershell lưu trữ một biến môi trường bình thường như mong đợi.
Dan

1
@Dan BTW: Tôi không bận tâm đến việc hạ cấp, nhưng cần lưu ý rằng phương pháp đã được chứng minh rõ ràng làm những gì người hỏi đã yêu cầu , vì vậy ngay cả khi có một cách tiếp cận thanh lịch hơn, nó vẫn sẽ là một giải pháp hợp lệ cho vấn đề.
the-wợi

1
@ the-wợi Nghe có vẻ như hành vi bình thường trong Windows. Ngay cả khi bạn cập nhật các biến môi trường toàn cầu, chỉ các quá trình bắt đầu kể từ khi cập nhật mới nhận ra sự thay đổi. Vì bạn đang nói về một quy trình cha mẹ , nó phải bắt đầu trước khi thay đổi. Điều tương tự cũng xảy ra với SETCommand Prompt. Hãy thử bắt đầu một đứa trẻ cmd.exevà bạn sẽ thấy điều tương tự. Mặc dù vậy, hành vi bạn thấy trong PowerShell là vì việc cập nhật các biến môi trường thông qua các lớp .NET không ảnh hưởng đến quy trình hiện tại.
jpmc26

4

Nếu nó là tôi, và kịch bản cha mẹ được một kịch bản shell, tôi chỉ muốn làm một gọi táo bạo của PowerShell trong kịch bản .CMD như:

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

Bạn có thể cần kiểm tra chính sách thực thi PowerShell của mình (lệnh ghép ngắn Set-ExecutPolicy).


3

Hoặc nếu bạn đã kết hôn để thực hiện việc này trong trình bao cũ, hãy bỏ qua PowerShell hoàn toàn.

Sử dụng biến% date% và mở rộng ngày từ chữ viết tắt mà nó đưa ra (điều này có thể bị ảnh hưởng bởi cài đặt định dạng ngày khu vực):

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

Lấy mã thông báo đầu tiên trong câu trả lời và mở rộng trên đó:

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

1
Windows 10 sẽ không hiển thị DOW trong% DATE%: H: \> echo% ngày% 20/03/2019
Raúl Salinas-Monteagudo

1

Trên thực tế, khi đặt một cái gì đó giống như bên dưới vào một tệp .ps1 (giả sử t.ps1) và gọi nó từ một phiên CMD với PowerShell -File t.ps1... nó hoạt động tốt.

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

Nhưng không phải cho phiên CMD nơi tập lệnh t.ps1 được gọi từ đó. Trong phiên CMD mới, chúng tôi nhận được:

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

Tôi đoán chúng ta phải tìm ra cách để hoàn thành một cái gì đó giống như export T=datetrong một phiên CMD.


1

Nếu bạn muốn tệp bó của bạn truy cập các biến môi trường được đặt bởi lệnh PowerShell chạy từ tệp bó đó, bạn có thể sử dụng cách giải quyết sau:

Tạo tập lệnh PowerShell của bạn tạo một tệp bó phụ mysub.bat, chứa các dòng "set biến = value" và thực thi tệp bó mysub.bat đó từ tệp bó chính ngay sau lệnh PowerShell.

Sử dụng phương thức WriteAllLines thay vì các phương thức đầu ra PowerShell mặc định để tệp bó phụ không được tạo với định dạng mã hóa UTF-8.

Thí dụ

chính.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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.