Có một lệnh để làm mới các biến môi trường từ dấu nhắc lệnh trong Windows không?


480

Nếu tôi sửa đổi hoặc thêm một biến môi trường, tôi phải khởi động lại dấu nhắc lệnh. Có một lệnh tôi có thể thực thi sẽ làm điều này mà không cần khởi động lại CMD?


38
Trên thực tế, mọi chương trình cần xem chúng đều phải được khởi động lại. Môi trường được sao chép vào bộ nhớ của quá trình khi khởi động và do đó không có kết nối nào với các envv do hệ thống xác định nữa.
Joey

15
Sau khi đọc những điều này, tôi nhận ra rằng không có muỗng ;) trong thế giới thực, bạn chỉ cần khởi động lại cmd.
n611x007

Không phải là một lệnh, vì vậy không hoàn toàn là một câu trả lời, nhưng có hỗ trợ cho nó bằng API Win32 nếu tôi đọc đúng như sau: support.microsoft.com/en-us/help/104011/ Lỗi Shoud có thể biên dịch dòng đó thành một chương trình C đơn giản và chạy nó sau khi cập nhật biến môi trường.
Charles Grunwald

WM_SETTINGCHANGE (api win32 được đề cập bởi @CharlesGrunwald) không hoạt động đối với các cửa sổ cmd.exe theo chủ đề này: github.com/chatioatey/choco/issues/1589 - đó là lý do họ đã viết lệnh refreshenv
davr

Câu trả lời:


137

Bạn có thể nắm bắt các biến môi trường hệ thống bằng tập lệnh vbs, nhưng bạn cần một tập lệnh bat để thực sự thay đổi các biến môi trường hiện tại, vì vậy đây là một giải pháp kết hợp.

Tạo một tệp có tên resetvars.vbschứa mã này và lưu nó trên đường dẫn:

Set oShell = WScript.CreateObject("WScript.Shell")
filename = oShell.ExpandEnvironmentStrings("%TEMP%\resetvars.bat")
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set oFile = objFileSystem.CreateTextFile(filename, TRUE)

set oEnv=oShell.Environment("System")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next
path = oEnv("PATH")

set oEnv=oShell.Environment("User")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next

path = path & ";" & oEnv("PATH")
oFile.WriteLine("SET PATH=" & path)
oFile.Close

tạo một tên tệp resetvars.bat có chứa mã này, cùng một vị trí:

@echo off
%~dp0resetvars.vbs
call "%TEMP%\resetvars.bat"

Khi bạn muốn làm mới các biến môi trường, chỉ cần chạy resetvars.bat


Lời xin lỗi :

Hai vấn đề chính tôi gặp phải với giải pháp này là

a. Tôi không thể tìm thấy một cách đơn giản để xuất các biến môi trường từ tập lệnh vbs trở lại dấu nhắc lệnh và

b. biến môi trường PATH là sự kết hợp của người dùng và các biến PATH của hệ thống.

Tôi không chắc quy tắc chung là gì đối với các biến xung đột giữa người dùng và hệ thống, vì vậy tôi đã chọn để tạo hệ thống ghi đè người dùng, ngoại trừ trong biến PATH được xử lý cụ thể.

Tôi sử dụng cơ chế lạ vbs + bat + bat để giải quyết vấn đề xuất biến từ vbs.

Lưu ý : tập lệnh này không xóa các biến.

Điều này có thể được cải thiện.

THÊM

Nếu bạn cần xuất môi trường từ cửa sổ cmd này sang cửa sổ khác, hãy sử dụng tập lệnh này (hãy gọi nó là exportvars.vbs):

Set oShell = WScript.CreateObject("WScript.Shell")
filename = oShell.ExpandEnvironmentStrings("%TEMP%\resetvars.bat")
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set oFile = objFileSystem.CreateTextFile(filename, TRUE)

set oEnv=oShell.Environment("Process")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next
oFile.Close

Chạy exportvars.vbstrong cửa sổ bạn muốn xuất khẩu từ , sau đó chuyển sang cửa sổ bạn muốn xuất khẩu tới , và gõ:

"%TEMP%\resetvars.bat"

2
Có lẽ bạn có thể tránh tệp tạm thời bằng cách sử dụng mã thông báo FOR / F "= 1, *" %% c IN ('resetvars.vbs') DO
tzot

2
Như tôi đã nói trong câu trả lời của mình "hoặc, thêm thủ công bằng cách sử dụng SET trong dấu nhắc lệnh hiện có." đó là những gì nó đang làm một cách hiệu quả. Câu trả lời tốt mặc dù.
Kev

2
@itsadok - cho rằng đây là câu trả lời được chấp nhận, bạn nên thêm một lời giải thích ngắn gọn khi bắt đầu để đặt tập lệnh vào ngữ cảnh. tức là chỉ ra rằng không thể truyền một thay đổi env sang cmd.exe mở mà không cập nhật thủ công như trên hoặc bằng cách khởi động lại cmd.exe.
Kev

Kịch bản xử lý trường hợp sử dụng thay đổi các biến môi trường trên toàn cầu trong "Biến máy tính của tôi ... Biến môi trường", nhưng nếu một biến môi trường được thay đổi trong một cmd.exe, tập lệnh sẽ không truyền nó sang một cmd.exe khác mà tôi nghĩ là có lẽ là một kịch bản phổ biến
Kev

1
@Keyslinger: Điều đó thực sự không thể. Bất kỳ chương trình nào được sinh ra đều có thể cập nhật môi trường riêng của nó, nhưng không phải là phiên bản cmd.exe đang chạy. Một tệp bó CÓ THỂ cập nhật môi trường cmd.exe, vì nó chạy trong cùng phiên bản của cmd.exe.
Ben Voigt

112

Đây là những gì Chocolatey sử dụng.

https://github.com/chocolatey/choco/blob/master/src/chocolatey.resource/redirects/RefreshEnv.cmd

@echo off
::
:: RefreshEnv.cmd
::
:: Batch file to read environment variables from registry and
:: set session variables to these values.
::
:: With this batch file, there should be no need to reload command
:: environment every time you want environment changes to propagate

echo | set /p dummy="Reading environment variables from registry. Please wait... "

goto main

:: Set one environment variable from registry key
:SetFromReg
    "%WinDir%\System32\Reg" QUERY "%~1" /v "%~2" > "%TEMP%\_envset.tmp" 2>NUL
    for /f "usebackq skip=2 tokens=2,*" %%A IN ("%TEMP%\_envset.tmp") do (
        echo/set %~3=%%B
    )
    goto :EOF

:: Get a list of environment variables from registry
:GetRegEnv
    "%WinDir%\System32\Reg" QUERY "%~1" > "%TEMP%\_envget.tmp"
    for /f "usebackq skip=2" %%A IN ("%TEMP%\_envget.tmp") do (
        if /I not "%%~A"=="Path" (
            call :SetFromReg "%~1" "%%~A" "%%~A"
        )
    )
    goto :EOF

:main
    echo/@echo off >"%TEMP%\_env.cmd"

    :: Slowly generating final file
    call :GetRegEnv "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" >> "%TEMP%\_env.cmd"
    call :GetRegEnv "HKCU\Environment">>"%TEMP%\_env.cmd" >> "%TEMP%\_env.cmd"

    :: Special handling for PATH - mix both User and System
    call :SetFromReg "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" Path Path_HKLM >> "%TEMP%\_env.cmd"
    call :SetFromReg "HKCU\Environment" Path Path_HKCU >> "%TEMP%\_env.cmd"

    :: Caution: do not insert space-chars before >> redirection sign
    echo/set Path=%%Path_HKLM%%;%%Path_HKCU%% >> "%TEMP%\_env.cmd"

    :: Cleanup
    del /f /q "%TEMP%\_envset.tmp" 2>nul
    del /f /q "%TEMP%\_envget.tmp" 2>nul

    :: Set these variables
    call "%TEMP%\_env.cmd"

    echo | set /p dummy="Done"
    echo .

65
+1 Nếu bạn đã cài đặt Chocolatey, bạn có thể chạy RefreshEnvđể nhận các biến môi trường được cập nhật vào phiên hiện tại của bạn.
Martin Valgur

2
Đây là một phần mềm cực kỳ hữu ích, cảm ơn rất nhiều vì đã chia sẻ.
Sabuncu

10
Lưu ý: Chocolatey đã chuyển repos và phiên bản mới nhất của tập lệnh này có thể được tìm thấy ở đây (với một số sửa lỗi): github.com/chatioatey/choco/blob/master/src/iêu
Michael Burr

1
Có nên làm việc này Powershellquá không? Nó dường như chỉ làm việc cmd.execho tôi.
craq

1
Nó hoạt động với tôi trong PowerShell, @craq. Chạy Windows10 x64.
mazunki

100

Trên Windows 7/8/10, bạn có thể cài đặt Chocolatey, có tập lệnh cho tích hợp này.

Sau khi cài đặt Chocolatey, chỉ cần gõ refreshenv.


đây là câu trả lời hợp lệ, sẽ rất tuyệt khi được nghe từ anh chàng đã đánh giá thấp nó
the_joric

2
Tôi đang làm gì sai? $> refreshenv 'refreshenv' không được công nhận là một lệnh nội bộ hoặc bên ngoài, chương trình có thể hoạt động hoặc tệp bó.
aclokay

@aclokay Không chắc chắn. Vui lòng cung cấp thêm chi tiết về hệ thống của bạn để gỡ lỗi. Trong khi đó bạn có thể tham khảo một vấn đề mở tương tự ở đây. github.com/chocolatey/choco/issues/250
vui vẻ

Nó cũng không làm việc cho tôi. Tôi đang sử dụng W7 chuyên nghiệp, có lẽ nó chỉ hoạt động trong các phiên bản hoàn chỉnh hơn.
kể cả

1
Nếu refreshenv sớm tồn tại tập lệnh của bạn (như đã làm với tôi), bạn có thể sử dụng "gọi RefreshEnv.cmd" để thay thế. (xem github.com/chocolatey/choco/issues/1461 )
sfiss

59

Theo thiết kế có không phải là một xây dựng trong cơ chế cho Windows để tuyên truyền một biến môi trường thêm / thay đổi / remove một cmd.exe đang chạy, hoặc từ cmd.exe khác hoặc từ "My Computer -> Properties -> Advanced Settings -> Biến môi trường ".

Nếu bạn sửa đổi hoặc thêm một biến môi trường mới bên ngoài phạm vi của dấu nhắc lệnh mở hiện có, bạn cần phải khởi động lại dấu nhắc lệnh hoặc thêm thủ công bằng cách sử dụng SET trong dấu nhắc lệnh hiện có.

Các mới nhất Câu trả lời được chấp nhận chương trình một công việc xung quanh một phần bằng cách thủ công làm mới tất cả các biến môi trường trong một kịch bản. Tập lệnh xử lý trường hợp sử dụng thay đổi các biến môi trường trên toàn cầu trong "Máy tính của tôi ... Biến môi trường", nhưng nếu một biến môi trường được thay đổi trong một cmd.exe, tập lệnh sẽ không truyền nó sang một cmd.exe khác đang chạy.


Nếu bất cứ ai có giải pháp làm việc cho vấn đề này, tôi sẽ kiểm tra định kỳ và có thể thay đổi câu trả lời được chấp nhận.
Eric Schoonover

1
Đây không phải là câu trả lời được chấp nhận đơn giản vì nó không trả lời câu hỏi được hỏi. câu hỏi này sẽ vẫn không có câu trả lời được chấp nhận cho đến khi tìm thấy câu trả lời.
shoosh

4
Và thật khó chịu, các trường hợp bổ sung của cmd.exe không được tính. Tất cả đều phải bị hủy trước khi thay đổi được phản ánh trong bất kỳ cmd.exe mới nào.

6
Các bình luận tiêu cực và đánh dấu xuống của câu trả lời này cho thấy mức độ tràn ngăn xếp bị hỏng đôi khi. Kev đã đưa ra câu trả lời chính xác. Chỉ vì bạn không thích nó không có lý do để đánh dấu nó xuống.
David Arno

Kev chắc chắn trả lời câu hỏi. Câu hỏi là không có giải pháp tích hợp.
Eric Schoonover

40

Tôi đã xem qua câu trả lời này trước khi tìm ra giải pháp dễ dàng hơn.

Chỉ cần khởi động lại explorer.exetrong Trình quản lý tác vụ.

Tôi đã không kiểm tra, nhưng bạn cũng có thể cần phải mở lại dấu nhắc lệnh.

Tín dụng cho Timo Huovinen tại đây: Nút không được công nhận mặc dù đã được cài đặt thành công (nếu điều này giúp bạn, vui lòng gửi tín dụng nhận xét của người đàn ông này).


Tôi đến đây vì tôi đang cố gắng thêm một công cụ bên ngoài vào phòng thu trực quan để tôi có thể mở một dấu nhắc lệnh ở gốc giải pháp của mình, như được mô tả trong blog này: neverindoubtnet.blogspot.com/2012/10/iêu ... và Tôi đã có vấn đề tương tự ... Tôi đã cố gắng để "git" xuất hiện trong biến đường dẫn của mình. Tôi đã thêm các thư mục git vào biến PATH nhưng sau đó chúng sẽ không xuất hiện trong dấu nhắc lệnh mà tôi sẽ mở từ Visual Studio. Giải pháp đơn giản là khởi động lại Visual Studio. Sau đó, các bổ sung mới cho biến PATH được hiển thị bằng cmd.
David Barrow

4
Giải pháp đó giúp tôi trong Windows 10
ganchito55

7
Câu hỏi là: "Có một lệnh tôi có thể thực thi sẽ làm điều này mà không cần khởi động lại CMD không?"
Florian F

Ok từ trình quản lý tác vụ tôi không thể khởi động lại explorer.exe, chỉ kết thúc anh ta. Tôi đã làm điều đó nhưng thanh nhiệm vụ của tôi đã bị phá vỡ. Để bắt đầu thám hiểm, exe nó thực sự đơn giản. Hãy để "Ctrl + shift + esc" -> tệp -> "thực thi tác vụ mới" -> "explorer.exe" đã làm việc cho tôi. Và có, sau khi tất cả var env đã được sử dụng trong cửa sổ cmd mới. Cảm ơn vì tất cả
Oscar

Giải pháp tốt, cảm ơn bạn! Để mở rộng và giải quyết nhận xét của @Oscar: Bắt đầu một cmdcửa sổ với tư cách Quản trị viên. Sử dụng lệnh taskkill /f /im explorer.exe && explorer.exe. Điều này sẽ giết quá trình explorer.exe và khởi động lại nó.
S3DEV

32

Điều này hoạt động trên windows 7: SET PATH=%PATH%;C:\CmdShortcuts

đã kiểm tra bằng cách gõ echo% PATH% và nó hoạt động tốt. cũng thiết lập nếu bạn mở một cmd mới, không cần những lần khởi động lại phiền phức nữa :)


1
Không hoạt động cho "cmd mới" đối với tôi (Win7 x64). Xem màn hình
Igor

26
Điều này không giải quyết được câu hỏi đang được hỏi, cũng không nên. Câu hỏi ban đầu là làm thế nào để làm mới một biến môi trường thành một giá trị đã được đặt ra ngoài thiết bị đầu cuối đó.
csauve

Mặc dù điều này không trả lời được câu hỏi, nhưng nó cung cấp một nửa giải pháp làm việc tốt nhất. Tôi sử dụng cái này - cho bất kỳ biến nào tôi đang cài đặt - sau đó tôi mở bảng điều khiển và thêm biến môi trường trên toàn cầu. Tôi không thích sử dụng setxvì nó kế thừa môi trường hiện tại có thể có các biến đã được sửa đổi và không phải là thứ tôi muốn vĩnh viễn. Làm theo cách này cho phép tôi tránh khởi động lại bàn điều khiển để sử dụng các biến, đồng thời tránh vấn đề không có sẵn chúng trên toàn cầu trong tương lai.
dgo

25

Sử dụng "setx" và khởi động lại dấu nhắc cmd

Có một công cụ dòng lệnh có tên là " setx " cho công việc này. Nó để đọc và viết các biến env. Các biến vẫn tồn tại sau khi cửa sổ lệnh đã được đóng.

Nó "Tạo hoặc sửa đổi các biến môi trường trong môi trường người dùng hoặc hệ thống, mà không yêu cầu lập trình hoặc tập lệnh. Lệnh setx cũng lấy các giá trị của các khóa đăng ký và ghi chúng vào tệp văn bản."

Lưu ý: các biến được tạo hoặc sửa đổi bởi công cụ này sẽ có sẵn trong các cửa sổ lệnh trong tương lai nhưng không có trong cửa sổ lệnh CMD.exe hiện tại. Vì vậy, bạn phải khởi động lại.

Nếu setxbị thiếu:


Hoặc sửa đổi sổ đăng ký

MSDN nói:

Để lập trình thêm hoặc sửa đổi các biến môi trường hệ thống, hãy thêm chúng vào HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ môi trường khóa, sau đó phát thông báo WM_SettINGCHANGE với lParam được đặt thành chuỗi " Môi trường ".

Điều này cho phép các ứng dụng, chẳng hạn như trình bao, nhận các bản cập nhật của bạn.


1
Bạn có thể mở rộng về cách sử dụng setx để đọc một biến môi trường không? Tôi đã xem qua các tài liệu khác nhau và tôi chỉ không thấy nó. : - /
Mark Ribau

2
setx VARIABLE -k "HKEY_LOCAL_MACHINE \ Software \ Microsoft \ WindowsNT \ CurrentVersion \ CurrentVersion" echo% VARIABLE%
Jens A. Koch

3
môi trường hệ thống hiện tại: môi trường HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\VARIABLEngười dùng hiện tại: HKEY_CURRENT_USER\Environment\VARIABLE
Mark Ribau

5
setx /? nói trong một lưu ý: "Trên một hệ thống cục bộ, các biến được tạo hoặc sửa đổi bởi công cụ này sẽ có sẵn trong các cửa sổ lệnh trong tương lai nhưng không có trong cửa sổ lệnh CMD.exe hiện tại ." OP muốn cập nhật cmd hiện tại.
Superole

4
Người mua hãy cẩn thận! Nếu bạn có một khoảng thời gian đặc biệt dài %PATH%thì setxcó thể cắt nó thành 1024 byte! Và cứ như thế, buổi tối của anh biến mất
FaCE

15

Gọi chức năng này đã làm việc cho tôi:

VOID Win32ForceSettingsChange()
{
    DWORD dwReturnValue;
    ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
}

8
và không phải tất cả các chương trình đều nghe tin nhắn này (thực tế hầu hết trong số họ có thể không nghe)
Rehan Khwaja

Không, nó cũng hoạt động cho các chương trình không phải GUI. Đối với các chương trình nghe ... vấn đề nếu đảm bảo rằng chương trình được khởi động lại sẽ nhận được môi trường cập nhật và điều này mang lại cho bạn điều đó.
2023370

11

Phương pháp tốt nhất tôi nghĩ ra là chỉ cần thực hiện một truy vấn Registry. Đây là ví dụ của tôi.

Trong ví dụ của tôi, tôi đã cài đặt bằng tệp Batch có thêm các biến môi trường mới. Tôi cần phải thực hiện mọi thứ với điều này ngay khi cài đặt hoàn tất, nhưng không thể tạo ra một quy trình mới với các biến mới đó. Tôi đã thử nghiệm sinh ra một cửa sổ thám hiểm khác và gọi lại cho cmd.exe và điều này đã hoạt động nhưng trên Vista và Windows 7, Explorer chỉ chạy như một phiên bản duy nhất và thông thường là người đăng nhập. Điều này sẽ thất bại với tự động hóa vì tôi cần quản trị viên của mình làm mọi việc bất kể chạy từ hệ thống cục bộ hoặc là quản trị viên trên hộp. Hạn chế của điều này là nó không xử lý những thứ như đường dẫn, điều này chỉ hoạt động trên các biến môi trường đơn giản. Điều này cho phép tôi sử dụng một lô để truy cập vào một thư mục (có dấu cách) và sao chép trong các tệp chạy .exes, v.v. Điều này được viết ngày hôm nay từ tài nguyên có thể trên stackoverflow.com

Orginal Batch gọi tới Batch mới:

testenvget.cmd SDROOT (hoặc bất cứ biến nào)

@ECHO OFF
setlocal ENABLEEXTENSIONS
set keyname=HKLM\System\CurrentControlSet\Control\Session Manager\Environment
set value=%1
SET ERRKEY=0

REG QUERY "%KEYNAME%" /v "%VALUE%" 2>NUL| FIND /I "%VALUE%"
IF %ERRORLEVEL% EQU 0 (
ECHO The Registry Key Exists 
) ELSE (
SET ERRKEY=1
Echo The Registry Key Does not Exist
)

Echo %ERRKEY%
IF %ERRKEY% EQU 1 GOTO :ERROR

FOR /F "tokens=1-7" %%A IN ('REG QUERY "%KEYNAME%" /v "%VALUE%" 2^>NUL^| FIND /I "%VALUE%"') DO (
ECHO %%A
ECHO %%B
ECHO %%C
ECHO %%D
ECHO %%E
ECHO %%F
ECHO %%G
SET ValueName=%%A
SET ValueType=%%B
SET C1=%%C
SET C2=%%D
SET C3=%%E
SET C4=%%F
SET C5=%%G
)

SET VALUE1=%C1% %C2% %C3% %C4% %C5%
echo The Value of %VALUE% is %C1% %C2% %C3% %C4% %C5%
cd /d "%VALUE1%"
pause
REM **RUN Extra Commands here**
GOTO :EOF

:ERROR
Echo The the Enviroment Variable does not exist.
pause
GOTO :EOF

Ngoài ra có một phương pháp khác mà tôi đã đưa ra từ nhiều ý tưởng khác nhau. Vui lòng xem bên dưới. Về cơ bản, điều này sẽ nhận được biến đường dẫn mới nhất từ ​​sổ đăng ký, tuy nhiên, điều này sẽ gây ra một số vấn đề khi sử dụng truy vấn đăng ký sẽ tự đưa ra các biến, điều đó có nghĩa là ở đâu cũng có một biến này sẽ không hoạt động, vì vậy để chống lại vấn đề này về cơ bản tăng gấp đôi đường dẫn. Rất khó chịu. Phương pháp được quan tâm nhiều hơn sẽ được thực hiện: Đặt Đường dẫn =% Đường dẫn%; C: \ Chương trình Tệp \ Phần mềm .... \

Bất kể ở đây là tập tin lô mới, xin vui lòng sử dụng thận trọng.

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
set org=%PATH%
for /f "tokens=2*" %%A in ('REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path ^|FIND /I "Path"') DO (
SET path=%%B
)
SET PATH=%org%;%PATH%
set path

8

Cách dễ nhất để thêm một biến vào đường dẫn mà không cần khởi động lại cho phiên hiện tại là mở dấu nhắc lệnh và gõ:

PATH=(VARIABLE);%path%

và nhấn enter.

để kiểm tra xem biến của bạn đã được tải chưa, gõ

PATH

và nhấn enter. Tuy nhiên, biến sẽ chỉ là một phần của đường dẫn cho đến khi bạn khởi động lại.


không hoạt động với tôi, không thể truy cập nhị phân trong biến đường dẫn
user2305193

7

Có thể thực hiện việc này bằng cách ghi đè Bảng Môi trường trong một quy trình được chỉ định.

Để chứng minh khái niệm, tôi đã viết ứng dụng mẫu này, nó chỉ chỉnh sửa một biến môi trường (đã biết) trong quy trình cmd.exe:

typedef DWORD (__stdcall *NtQueryInformationProcessPtr)(HANDLE, DWORD, PVOID, ULONG, PULONG);

int __cdecl main(int argc, char* argv[])
{
    HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
    NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hNtDll, "NtQueryInformationProcess");

    int processId = atoi(argv[1]);
    printf("Target PID: %u\n", processId);

    // open the process with read+write access
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, 0, processId);
    if(hProcess == NULL)
    {
        printf("Error opening process (%u)\n", GetLastError());
        return 0;
    }

    // find the location of the PEB
    PROCESS_BASIC_INFORMATION pbi = {0};
    NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
    if(status != 0)
    {
        printf("Error ProcessBasicInformation (0x%8X)\n", status);
    }
    printf("PEB: %p\n", pbi.PebBaseAddress);

    // find the process parameters
    char *processParamsOffset = (char*)pbi.PebBaseAddress + 0x20; // hard coded offset for x64 apps
    char *processParameters = NULL;
    if(ReadProcessMemory(hProcess, processParamsOffset, &processParameters, sizeof(processParameters), NULL))
    {
        printf("UserProcessParameters: %p\n", processParameters);
    }
    else
    {
        printf("Error ReadProcessMemory (%u)\n", GetLastError());
    }

    // find the address to the environment table
    char *environmentOffset = processParameters + 0x80; // hard coded offset for x64 apps
    char *environment = NULL;
    ReadProcessMemory(hProcess, environmentOffset, &environment, sizeof(environment), NULL);
    printf("environment: %p\n", environment);

    // copy the environment table into our own memory for scanning
    wchar_t *localEnvBlock = new wchar_t[64*1024];
    ReadProcessMemory(hProcess, environment, localEnvBlock, sizeof(wchar_t)*64*1024, NULL);

    // find the variable to edit
    wchar_t *found = NULL;
    wchar_t *varOffset = localEnvBlock;
    while(varOffset < localEnvBlock + 64*1024)
    {
        if(varOffset[0] == '\0')
        {
            // we reached the end
            break;
        }
        if(wcsncmp(varOffset, L"ENVTEST=", 8) == 0)
        {
            found = varOffset;
            break;
        }
        varOffset += wcslen(varOffset)+1;
    }

    // check to see if we found one
    if(found)
    {
        size_t offset = (found - localEnvBlock) * sizeof(wchar_t);
        printf("Offset: %Iu\n", offset);

        // write a new version (if the size of the value changes then we have to rewrite the entire block)
        if(!WriteProcessMemory(hProcess, environment + offset, L"ENVTEST=def", 12*sizeof(wchar_t), NULL))
        {
            printf("Error WriteProcessMemory (%u)\n", GetLastError());
        }
    }

    // cleanup
    delete[] localEnvBlock;
    CloseHandle(hProcess);

    return 0;
}

Đầu ra mẫu:

>set ENVTEST=abc

>cppTest.exe 13796
Target PID: 13796
PEB: 000007FFFFFD3000
UserProcessParameters: 00000000004B2F30
environment: 000000000052E700
Offset: 1528

>set ENVTEST
ENVTEST=def

Ghi chú

Cách tiếp cận này cũng sẽ được giới hạn trong các hạn chế bảo mật. Nếu mục tiêu được chạy ở độ cao cao hơn hoặc tài khoản cao hơn (chẳng hạn như HỆ THỐNG) thì chúng tôi sẽ không được phép chỉnh sửa bộ nhớ của nó.

Nếu bạn muốn thực hiện điều này với ứng dụng 32 bit, phần bù được mã hóa cứng ở trên sẽ thay đổi thành 0x10 và 0x48 tương ứng. Có thể tìm thấy các độ lệch này bằng cách loại bỏ _PEB và _RTL_USER_PROCESS_PARAMETERS trong trình gỡ lỗi (ví dụ: trong WinDbg dt _PEBdt _RTL_USER_PROCESS_PARAMETERS)

Để thay đổi khái niệm bằng chứng thành những gì OP cần, nó sẽ chỉ liệt kê các biến môi trường người dùng và hệ thống hiện tại (như tài liệu của câu trả lời của @ tsadok) và ghi toàn bộ bảng môi trường vào bộ nhớ của quá trình đích.

Chỉnh sửa: Kích thước của khối môi trường cũng được lưu trữ trong cấu trúc _RTL_USER_PROCESS_PARAMETERS, nhưng bộ nhớ được phân bổ trên heap của tiến trình. Vì vậy, từ quy trình bên ngoài, chúng tôi sẽ không có khả năng thay đổi kích thước và làm cho nó lớn hơn. Tôi đã chơi xung quanh với việc sử dụng VirtualAllocEx để phân bổ bộ nhớ bổ sung trong quy trình đích cho bộ lưu trữ môi trường và có thể đặt và đọc một bảng hoàn toàn mới. Thật không may, bất kỳ nỗ lực nào để sửa đổi môi trường từ các phương tiện thông thường sẽ bị sập và cháy do địa chỉ không còn trỏ đến heap (nó sẽ bị sập trong RtlSizeHeap).


6

Các biến môi trường được giữ trong HKEY_LOCAL_MACHINE \ HỆ THỐNG \ ControlSet \ Control \ Trình quản lý phiên \ Môi trường.

Nhiều vars env hữu ích, chẳng hạn như Path, được lưu trữ dưới dạng REG_SZ. Có một số cách để truy cập vào sổ đăng ký, bao gồm cả REGEDIT:

REGEDIT /E &lt;filename&gt; "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment"

Đầu ra bắt đầu với số ma thuật. Vì vậy, để tìm kiếm nó bằng lệnh find, nó cần được gõ và chuyển hướng:type <filename> | findstr -c:\"Path\"

Vì vậy, nếu bạn chỉ muốn làm mới biến đường dẫn trong phiên lệnh hiện tại của mình với thuộc tính hệ thống thì tập lệnh bó sau hoạt động tốt:

Làm mớiPath.cmd:

    @echo tắt

    REM Giải pháp này yêu cầu độ cao để đọc từ sổ đăng ký.

    nếu tồn tại% temp% \ env.reg del% temp% \ env.reg / q / f

    REGEDIT / E% temp% \ env.reg "HKEY_LOCAL_MACHINE \ HỆ THỐNG \ ControlSet001 \ Control \ Trình quản lý phiên \ Môi trường"

    nếu không tồn tại% temp% \ env.reg (
       echo "Không thể ghi registry vào vị trí tạm thời"
       thoát 1
       )

    SETLOCAL EnableDelayedExpansion

    for / f "tokens = 1,2 * delims ==" %% i in ('gõ% temp% \ env.reg ^ | findstr -c: \ "Path \" =') do (
       thiết lập upath = %% ~ j
       echo! upath: \\ = \! >% tạm thời% \ newpath
       )

     KẾT THÚC

     for / f "tokens = *" %% i trong (% temp% \ newpath) thực hiện đặt đường dẫn = %% i

5
Biến môi trường không được giữ trong sổ đăng ký. Những gì được giữ trong sổ đăng ký là một mẫu , từ đó các chương trình như Windows Explorer (tái) xây dựng các biến môi trường của chúng khi được thông báo để làm như vậy . Các biến môi trường thực tế là mỗi quy trình và được lưu trữ trong không gian địa chỉ riêng của từng quy trình, ban đầu được kế thừa từ quy trình mẹ của nó và có thể sửa đổi sau đó tại quy trình.
JdeBP

5

Hãy thử mở một dấu nhắc lệnh mới với tư cách quản trị viên. Điều này làm việc cho tôi trên Windows 10. (Tôi biết đây là một câu trả lời cũ, nhưng tôi đã phải chia sẻ điều này vì phải viết một kịch bản VBS chỉ vì điều này là vô lý).


5

Khởi động lại explorer đã làm điều này cho tôi, nhưng chỉ cho các thiết bị đầu cuối cmd mới.

Thiết bị đầu cuối tôi đặt đường dẫn có thể thấy biến Đường dẫn mới (trong Windows 7).

taskkill /f /im explorer.exe && explorer.exe

5

Điều khó hiểu có thể là có một vài nơi để bắt đầu cmd từ đó. Trong trường hợp của tôi, tôi đã chạy cmd từ windows explorer và các biến môi trường không thay đổi trong khi khi bắt đầu cmd từ "run" (phím windows + r), các biến môi trường đã thay đổi .

Trong trường hợp của tôi, tôi chỉ phải giết tiến trình windows explorer từ trình quản lý tác vụ và sau đó khởi động lại từ trình quản lý tác vụ .

Khi tôi đã làm điều này, tôi có quyền truy cập vào biến môi trường mới từ một cmd được sinh ra từ windows explorer.


3

Tôi sử dụng đoạn mã sau trong tập lệnh bó của mình:

if not defined MY_ENV_VAR (
    setx MY_ENV_VAR "VALUE" > nul
    set MY_ENV_VAR=VALUE
)
echo %MY_ENV_VAR%

Bằng cách sử dụng SET sau SETX , có thể sử dụng biến "cục bộ" trực tiếp mà không cần khởi động lại cửa sổ lệnh. Và trong lần chạy tiếp theo, biến môi trường sẽ được sử dụng.


Trong khi tôi nhận được những gì bạn đã làm, rất có thể anh ta muốn một cái gì đó cho các tập lệnh song song, một tập lệnh đặt toàn cục trong khi một tập lệnh khác đọc chúng. Mặt khác, không có điểm nào liên quan đến setx, set sẽ là đủ.
JasonXA

3

Tôi thích cách tiếp cận của sô cô la, như được đăng trong câu trả lời của kẻ hèn nhát ẩn danh, vì đó là một cách tiếp cận thuần túy. Tuy nhiên, nó để lại một tập tin tạm thời và một số biến tạm thời nằm xung quanh. Tôi đã tạo ra một phiên bản sạch hơn cho chính mình.

Tạo một tập tin refreshEnv.batở đâu đó trên của bạn PATH. Làm mới môi trường giao diện điều khiển của bạn bằng cách thực hiện refreshEnv.

@ECHO OFF
REM Source found on https://github.com/DieterDePaepe/windows-scripts
REM Please share any improvements made!

REM Code inspired by http://stackoverflow.com/questions/171588/is-there-a-command-to-refresh-environment-variables-from-the-command-prompt-in-w

IF [%1]==[/?] GOTO :help
IF [%1]==[/help] GOTO :help
IF [%1]==[--help] GOTO :help
IF [%1]==[] GOTO :main

ECHO Unknown command: %1
EXIT /b 1 

:help
ECHO Refresh the environment variables in the console.
ECHO.
ECHO   refreshEnv       Refresh all environment variables.
ECHO   refreshEnv /?        Display this help.
GOTO :EOF

:main
REM Because the environment variables may refer to other variables, we need a 2-step approach.
REM One option is to use delayed variable evaluation, but this forces use of SETLOCAL and
REM may pose problems for files with an '!' in the name.
REM The option used here is to create a temporary batch file that will define all the variables.

REM Check to make sure we don't overwrite an actual file.
IF EXIST %TEMP%\__refreshEnvironment.bat (
  ECHO Environment refresh failed!
  ECHO.
  ECHO This script uses a temporary file "%TEMP%\__refreshEnvironment.bat", which already exists. The script was aborted in order to prevent accidental data loss. Delete this file to enable this script.
  EXIT /b 1
)

REM Read the system environment variables from the registry.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"`) DO (
  REM /I -> ignore casing, since PATH may also be called Path
  IF /I NOT [%%I]==[PATH] (
    ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
  )
)

REM Read the user environment variables from the registry.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment`) DO (
  REM /I -> ignore casing, since PATH may also be called Path
  IF /I NOT [%%I]==[PATH] (
    ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
  )
)

REM PATH is a special variable: it is automatically merged based on the values in the
REM system and user variables.
REM Read the PATH variable from the system and user environment variables.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH`) DO (
  ECHO SET PATH=%%K>>%TEMP%\__refreshEnvironment.bat
)
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment /v PATH`) DO (
  ECHO SET PATH=%%PATH%%;%%K>>%TEMP%\__refreshEnvironment.bat
)

REM Load the variable definitions from our temporary file.
CALL %TEMP%\__refreshEnvironment.bat

REM Clean up after ourselves.
DEL /Q %TEMP%\__refreshEnvironment.bat

ECHO Environment successfully refreshed.

đây cũng là cho% CLIENTNAME% phải không? - không hoạt động với tôi - stackoverflow.com/questions/37550160/ Kẻ
Igor L.

% CLIENTNAME% không khả dụng trong môi trường của tôi và bằng cách đọc câu hỏi của bạn, tôi sẽ cho rằng đó là thứ gì đó được đặt ra bởi một quy trình bên ngoài. (Khi một quá trình bắt đầu một tiến trình con, nó có thể điều chỉnh môi trường cho đứa trẻ đó.) Vì nó không phải là một phần của các biến môi trường thực tế, nên kịch bản này sẽ không được cập nhật.
DieterDP

Xin chào @DieterDP, giải pháp của bạn hiệu quả với tôi! Tôi đang sử dụng Windows 10 trên máy 64 bit. Tôi gặp lỗi: "LRI: Hệ thống không thể tìm thấy khóa hoặc giá trị đăng ký được chỉ định.". Tuy nhiên, việc cập nhật các biến môi trường là thành công. Lỗi đến từ đâu?
K.Mulier

Thật khó để nói mà không thực sự tự kiểm tra nó, nhưng tôi đoán cấu trúc đăng ký trên W10 có thể hơi khác nhau. Nếu bạn cảm thấy thích nó, hãy thử tìm kiếm lỗi bằng cách thực hiện các lệnh trên dòng lệnh.
DieterDP

2

Nếu nó chỉ liên quan đến một (hoặc một vài) lọ cụ thể mà bạn muốn thay đổi, tôi nghĩ cách dễ nhất là một cách giải quyết : chỉ cần đặt trong môi trường của bạn VÀ trong phiên bảng điều khiển hiện tại của bạn

  • Set sẽ đặt var trong phiên hiện tại của bạn
  • SetX sẽ đặt var trong môi trường, nhưng KHÔNG trong phiên hiện tại của bạn

Tôi có tập lệnh bó đơn giản này để thay đổi Maven của tôi từ Java7 thành Java8 (cả hai đều là vars) Thư mục bó nằm trong var PATH của tôi để tôi luôn có thể gọi ' j8 ' và trong bảng điều khiển của mình và trong môi trường được thay đổi:

j8.bat:

@echo off
set JAVA_HOME=%JAVA_HOME_8%
setx JAVA_HOME "%JAVA_HOME_8%"

Cho đến bây giờ tôi thấy điều này làm việc tốt nhất và dễ dàng nhất. Bạn có thể muốn điều này nằm trong một lệnh, nhưng đơn giản là nó không có trong Windows ...


2

Giải pháp tôi đã sử dụng vài năm nay:

@echo off
rem Refresh PATH from registry.
setlocal
set USR_PATH=
set SYS_PATH=
for /F "tokens=3* skip=2" %%P in ('%SystemRoot%\system32\reg.exe query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH') do @set "SYS_PATH=%%P %%Q"
for /F "tokens=3* skip=2" %%P in ('%SystemRoot%\system32\reg.exe query "HKCU\Environment" /v PATH') do @set "USR_PATH=%%P %%Q"
if "%SYS_PATH:~-1%"==" " set "SYS_PATH=%SYS_PATH:~0,-1%"
if "%USR_PATH:~-1%"==" " set "USR_PATH=%USR_PATH:~0,-1%"
endlocal & call set "PATH=%SYS_PATH%;%USR_PATH%"
goto :EOF

Chỉnh sửa: Woops, đây là phiên bản cập nhật.


Tôi thích câu trả lời của bạn. Gửi câu trả lời tương tự cho câu hỏi của tôi ở đây stackoverflow.com/q/61473551/1082063 và tôi sẽ chấp nhận nó như những câu trả lời. Cảm ơn.
David I. McIntosh

1

Không có cách nào thẳng, như Kev nói. Trong hầu hết các trường hợp, việc sinh ra một hộp CMD khác sẽ đơn giản hơn. Khó chịu hơn, các chương trình đang chạy cũng không biết về các thay đổi (mặc dù IIRC có thể có một thông báo quảng bá để xem để được thông báo về sự thay đổi đó).

Điều tồi tệ hơn là: trong các phiên bản Windows cũ hơn, bạn phải đăng xuất sau đó đăng nhập lại để xem xét các thay đổi ...


1

Tôi sử dụng tập lệnh Powershell này để thêm vào biến PATH . Với một chút điều chỉnh nó cũng có thể hoạt động trong trường hợp của bạn.

#REQUIRES -Version 3.0

if (-not ("win32.nativemethods" -as [type])) {
    # import sendmessagetimeout from win32
    add-type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
   IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
   uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}

$HWND_BROADCAST = [intptr]0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [uintptr]::zero

function global:ADD-PATH
{
    [Cmdletbinding()]
    param ( 
        [parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)] 
        [string] $Folder
    )

    # See if a folder variable has been supplied.
    if (!$Folder -or $Folder -eq "" -or $Folder -eq $null) { 
        throw 'No Folder Supplied. $ENV:PATH Unchanged'
    }

    # Get the current search path from the environment keys in the registry.
    $oldPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path

    # See if the new Folder is already in the path.
    if ($oldPath | Select-String -SimpleMatch $Folder){ 
        return 'Folder already within $ENV:PATH' 
    }

    # Set the New Path and add the ; in front
    $newPath=$oldPath+';'+$Folder
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop

    # Show our results back to the world
    return 'This is the new PATH content: '+$newPath

    # notify all windows of environment block change
    [win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}

function global:REMOVE-PATH {
    [Cmdletbinding()]
    param ( 
        [parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)]
        [String] $Folder
    )

    # See if a folder variable has been supplied.
    if (!$Folder -or $Folder -eq "" -or $Folder -eq $NULL) { 
        throw 'No Folder Supplied. $ENV:PATH Unchanged'
    }

    # add a leading ";" if missing
    if ($Folder[0] -ne ";") {
        $Folder = ";" + $Folder;
    }

    # Get the Current Search Path from the environment keys in the registry
    $newPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path

    # Find the value to remove, replace it with $NULL. If it's not found, nothing will change and you get a message.
    if ($newPath -match [regex]::Escape($Folder)) { 
        $newPath=$newPath -replace [regex]::Escape($Folder),$NULL 
    } else { 
        return "The folder you mentioned does not exist in the PATH environment" 
    }

    # Update the Environment Path
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop

    # Show what we just did
    return 'This is the new PATH content: '+$newPath

    # notify all windows of environment block change
    [win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}


# Use ADD-PATH or REMOVE-PATH accordingly.

#Anything to Add?

#Anything to Remove?

REMOVE-PATH "%_installpath_bin%"

1

Cảm ơn bạn đã đăng câu hỏi này khá thú vị, ngay cả trong năm 2019 (Thật vậy, không dễ để làm mới cmd shell vì đây là một trường hợp duy nhất như đã đề cập ở trên), vì làm mới các biến môi trường trong windows cho phép thực hiện nhiều tác vụ tự động hóa mà không cần phải tự khởi động lại dòng lệnh.

Ví dụ: chúng tôi sử dụng điều này để cho phép phần mềm được triển khai và định cấu hình trên một số lượng lớn máy mà chúng tôi cài đặt lại thường xuyên. Và tôi phải thừa nhận rằng việc phải khởi động lại dòng lệnh trong quá trình triển khai phần mềm của chúng tôi sẽ rất không thực tế và sẽ yêu cầu chúng tôi tìm cách giải quyết không nhất thiết phải dễ chịu. Hãy đi đến vấn đề của chúng tôi. Chúng tôi tiến hành như sau.

1 - Chúng tôi có một tập lệnh bó mà lần lượt gọi một tập lệnh powershell như thế này

[tập tin: task.cmd] .

cmd > powershell.exe -executionpolicy unrestricted -File C:\path_here\refresh.ps1

2 - Sau này, tập lệnh refresh.ps1 làm mới các biến môi trường bằng các khóa đăng ký (GetValueNames (), v.v.). Sau đó, trong cùng một tập lệnh powershell, chúng ta chỉ cần gọi các biến môi trường mới có sẵn. Ví dụ, trong một trường hợp điển hình, nếu chúng ta vừa cài đặt nodeJS trước với cmd bằng các lệnh im lặng, sau khi hàm được gọi, chúng ta có thể gọi trực tiếp npm để cài đặt, trong cùng một phiên, các gói cụ thể như sau.

[tập tin: refresh.ps1]

function Update-Environment {
    $locations = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session  Manager\Environment',
                 'HKCU:\Environment'
    $locations | ForEach-Object {
        $k = Get-Item $_
        $k.GetValueNames() | ForEach-Object {
            $name  = $_
            $value = $k.GetValue($_)

            if ($userLocation -and $name -ieq 'PATH') {
                $env:Path += ";$value"
            } else {

                Set-Item -Path Env:\$name -Value $value
            }
        }
        $userLocation = $true
    }
}
Update-Environment
#Here we can use newly added environment variables like for example npm install.. 
npm install -g create-react-app serve

Khi tập lệnh powershell kết thúc, tập lệnh cmd tiếp tục với các tác vụ khác. Bây giờ, một điều cần lưu ý là sau khi tác vụ hoàn thành, cmd vẫn không có quyền truy cập vào các biến môi trường mới, ngay cả khi tập lệnh powershell đã cập nhật chúng trong phiên của chính nó. Đó là lý do tại sao chúng ta thực hiện tất cả các tác vụ cần thiết trong tập lệnh powershell có thể gọi các lệnh tương tự như cmd.


0

Chỉnh sửa: điều này chỉ hoạt động nếu môi trường thay đổi bạn đang làm là kết quả của việc chạy một tệp bó.

Nếu một tệp bó bắt đầu bằng SETLOCALthì nó sẽ luôn làm sáng trở lại môi trường ban đầu của bạn khi thoát ngay cả khi bạn quên gọi ENDLOCALtrước khi thoát hàng loạt hoặc nếu nó hủy bỏ bất ngờ.

Hầu như mọi tệp tin tôi viết đều bắt đầu SETLOCALvì trong hầu hết các trường hợp tôi không muốn các tác dụng phụ của thay đổi môi trường vẫn còn. Trong trường hợp tôi muốn thay đổi biến môi trường nhất định để truyền bên ngoài tệp bó thì lần cuối cùng của tôi ENDLOCALtrông như thế này:

ENDLOCAL & (
  SET RESULT1=%RESULT1%
  SET RESULT2=%RESULT2%
)

-1

Để giải quyết vấn đề này, tôi đã thay đổi biến môi trường bằng BOTH setx và set, sau đó khởi động lại tất cả các phiên bản của explorer.exe. Bằng cách này, bất kỳ quá trình nào sau đó được bắt đầu sẽ có biến môi trường mới.

Tập lệnh bó của tôi để làm điều này:

setx /M ENVVAR "NEWVALUE"
set ENVVAR="NEWVALUE"

taskkill /f /IM explorer.exe
start explorer.exe >nul
exit

Vấn đề với cách tiếp cận này là tất cả các cửa sổ explorer hiện đang mở sẽ bị đóng, đây có thể là một ý tưởng tồi - Nhưng hãy xem bài đăng của Kev để tìm hiểu lý do tại sao điều này là cần thiết

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.