จะอัปเดตตัวแปร PATH อย่างถาวรจากบรรทัดคำสั่งของ Windows ได้อย่างไร


122

ถ้าฉันดำเนินการset PATH=%PATH%;C:\\Something\\binจากบรรทัดคำสั่ง ( cmd.exe) แล้วดำเนินการecho %PATH%ฉันเห็นสตริงนี้เพิ่มใน PATH ถ้าฉันปิดและเปิดบรรทัดคำสั่งสตริงใหม่นั้นจะไม่อยู่ใน PATH

ฉันจะอัปเดต PATH อย่างถาวรจากบรรทัดคำสั่งสำหรับกระบวนการทั้งหมดในอนาคตได้อย่างไรไม่ใช่เฉพาะสำหรับกระบวนการปัจจุบัน

ฉันไม่ต้องการทำสิ่งนี้โดยไปที่คุณสมบัติของระบบ→ขั้นสูง→ตัวแปรสภาพแวดล้อมและอัปเดต PATH ที่นั่น

คำสั่งนี้ต้องดำเนินการจากแอปพลิเคชัน Java (โปรดดูคำถามอื่นของฉัน)


5
ใช้ PowerShell ก็ straightfoward ธรรมstackoverflow.com/questions/714877/... ใช้ cmd ผมไม่แน่ใจ คุณอาจต้องแก้ไขรีจิสทรีหรือดึง. net ประกอบขึ้นมา
Austen Holmes

1
อย่างที่บอกว่าต้องทำจากในแอปพลิเคชัน java ฉันคิดว่าจะดำเนินการคำสั่ง cmd บางคำสั่ง useng javaRuntime.getRuntime().exec("my command");
vale4674

คำตอบ:


43

เอกสารเกี่ยวกับวิธีการทำเช่นนี้สามารถพบได้บนMSDN สารสกัดที่สำคัญคือ:

หากต้องการเพิ่มหรือแก้ไขตัวแปรสภาพแวดล้อมระบบโดยทางโปรแกรมให้เพิ่มลงในคีย์รีจิสทรีHKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environmentจากนั้นออกอากาศWM_SETTINGCHANGEข้อความโดยตั้งค่า lParam เป็นสตริง "Environment" ซึ่งช่วยให้แอปพลิเคชันเช่นเชลล์สามารถรับการอัปเดตของคุณได้

โปรดทราบว่าแอปพลิเคชันของคุณจะต้องมีการยกระดับสิทธิ์ของผู้ดูแลระบบเพื่อให้สามารถแก้ไขคีย์นี้ได้

คุณระบุในความคิดเห็นว่าคุณยินดีที่จะแก้ไขเฉพาะสภาพแวดล้อมต่อผู้ใช้ ทำเช่นนี้โดยการแก้ไขค่าในHKEY_CURRENT_USER \ สิ่งแวดล้อม เช่นเดิมตรวจสอบให้แน่ใจว่าคุณได้เผยแพร่WM_SETTINGCHANGEข้อความ

คุณควรจะสามารถทำได้จากแอปพลิเคชัน Java ของคุณได้อย่างง่ายดายโดยใช้คลาสรีจิสทรี JNI


1
ใช่โดยใช้คลาสรีจิสทรี JNI ปัญหาที่ใหญ่กว่าคือแอปของคุณอาจไม่ทำงานในระดับสูง คุณรู้หรือไม่ว่าจะทำอย่างไร? หากคุณต้องการเพียงส่วนเล็ก ๆ ของแอปของคุณในการทำงานในระดับสูง (เช่นเพื่อทำการเปลี่ยนแปลงนี้) ทางออกที่ง่ายที่สุดคือแอป C ++ ที่ง่ายมากในการทำงานโดยทำเครื่องหมายด้วยรายการแอปจากนั้นจึงดำเนินการเป็นกระบวนการแยกต่างหากซึ่ง กระตุ้นกล่องโต้ตอบ UAC
David Heffernan

1
คุณยังสามารถแก้ไขHKEY_CURRENT_USER\Environmentเพื่อหลีกเลี่ยงความต้องการระดับความสูง
kichik

@David Heffernan ใช่มีเพียงสิ่งนี้เท่านั้นที่ต้องทำงานในระดับสูง ดังนั้นคำแนะนำของคุณคือเขียนแอปพลิเคชัน C ++ และเรียกใช้งานจากแอปพลิเคชัน java ของฉันหรือไม่? คุณช่วยให้รหัสตัวอย่างหรือลิงค์เกี่ยวกับวิธีดำเนินการนี้ได้ไหม
vale4674

อ๋อ เหมือนที่เดวิดพูด เพียงคุณไม่ยกระดับ ฉันควรพูดถึงสิ่งนี้จะปรับเปลี่ยนสภาพแวดล้อมสำหรับผู้ใช้ปัจจุบันเท่านั้น
kichik

คุณต้องแยกสิ่งนี้ออกเป็นกระบวนการแยกต่างหากเพื่อที่คุณจะบังคับไดอะล็อก UAC เมื่อแก้ไข PATH ของระบบเท่านั้น เพียงแค่ต้องการแอป C ++ ที่เรียบง่ายพร้อมด้วยการอ่านและเขียนรีจิสทรีสองสามรายการตามด้วย SendMessage การตั้งค่าrequestedExecutionLevelไปrequireAdministratorในแอปอย่างชัดแจ้ง
David Heffernan

145

คุณสามารถใช้ได้:

setx PATH "%PATH%;C:\\Something\\bin"

อย่างไรก็ตามsetxจะตัดสตริงที่เก็บไว้ให้เหลือ 1024 ไบต์ซึ่งอาจทำให้ PATH เสียหายได้

/Mจะเปลี่ยนPATHในแทนHKEY_LOCAL_MACHINE HKEY_CURRENT_USERกล่าวอีกนัยหนึ่งคือตัวแปรระบบแทนที่จะเป็นของผู้ใช้ ตัวอย่างเช่น:

SETX /M PATH "%PATH%;C:\your path with spaces"

คุณต้องจำไว้ว่า PATH ใหม่จะไม่ปรากฏในปัจจุบันของคุณ cmd.exeคุณจะต้องเก็บไว้ในใจเส้นทางใหม่ไม่ได้มองเห็นได้ในปัจจุบันของคุณ

แต่ถ้าคุณดูในรีจิสตรีหรือใหม่cmd.exeด้วย"set p"คุณจะเห็นค่าใหม่


2
มีวิธีใช้setxเปลี่ยนเส้นทางของเครื่องแทนเส้นทางของผู้ใช้หรือไม่?
Corey Ogburn

4
จากที่นี่คุณสามารถบอกได้ว่าอาจเป็นไปได้ที่จะตั้งค่าตัวแปรไม่เพียง แต่สำหรับผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน แต่สำหรับเครื่องโดยใช้/mท้ายคำสั่งบน windows xp และ 7 ฉันยังไม่ได้ลอง
panny

1
ฉันได้รับข้อผิดพลาดเมื่อเรียกใช้setxคำสั่ง "Default option is not allow over over '2' time" จะข้ามได้อย่างไร?
Nam G VU

12
ความคิดเห็น @KilgoreCod: ฉันขอเตือนไม่ให้ใช้คำสั่ง: ในการติดตั้งหลาย ๆ (ส่วนใหญ่?) ทุกวันนี้ตัวแปร PATH จะมีความยาว - setx จะตัดสตริงที่เก็บไว้ให้เหลือ 1024 ไบต์ซึ่งอาจทำให้ PATH เสียหาย (ดูการสนทนาที่นี่superuser.com/ q / 812754 )
beresfordt

2
ฉันพยายามสะท้อนเส้นทางที่มีอยู่แล้วมากกว่า 1200 ไบต์ วิธีอื่นแทน setx หรือไม่?
lawphotog

37

ฉันเตือนไม่ให้ใช้คำสั่ง

setx PATH "%PATH%;C:\Something\bin"

เพื่อแก้ไขตัวแปร PATH เนื่องจาก "คุณลักษณะ" ของการนำไปใช้งาน ในการติดตั้งหลาย ๆ (ส่วนใหญ่?) ในปัจจุบันตัวแปรจะมีความยาว - setxจะตัดทอนสตริงที่เก็บไว้ให้เหลือ 1024 ไบต์ซึ่งอาจทำให้ PATH เสียหาย (ดูการอภิปรายที่นี่ )

( ฉันลงทะเบียนโดยเฉพาะเพื่อตั้งค่าสถานะปัญหานี้ดังนั้นจึงไม่มีชื่อเสียงของไซต์ในการแสดงความคิดเห็นโดยตรงกับคำตอบที่โพสต์เมื่อวันที่ 2 พฤษภาคม 2555 ขอบคุณ beresfordt สำหรับการเพิ่มความคิดเห็นดังกล่าว )


9

Python-script [*] นี้ทำอย่างนั้น:

"""
Show/Modify/Append registry env-vars (ie `PATH`) and notify Windows-applications to pickup changes.

First attempts to show/modify HKEY_LOCAL_MACHINE (all users), and 
if not accessible due to admin-rights missing, fails-back 
to HKEY_CURRENT_USER.
Write and Delete operations do not proceed to user-tree if all-users succeed.

Syntax: 
    {prog}                  : Print all env-vars. 
    {prog}  VARNAME         : Print value for VARNAME. 
    {prog}  VARNAME   VALUE : Set VALUE for VARNAME. 
    {prog}  +VARNAME  VALUE : Append VALUE in VARNAME delimeted with ';' (i.e. used for `PATH`). 
    {prog}  -VARNAME        : Delete env-var value. 

Note that the current command-window will not be affected, 
changes would apply only for new command-windows.
"""

import winreg
import os, sys, win32gui, win32con

def reg_key(tree, path, varname):
    return '%s\%s:%s' % (tree, path, varname) 

def reg_entry(tree, path, varname, value):
    return '%s=%s' % (reg_key(tree, path, varname), value)

def query_value(key, varname):
    value, type_id = winreg.QueryValueEx(key, varname)
    return value

def yield_all_entries(tree, path, key):
    i = 0
    while True:
        try:
            n,v,t = winreg.EnumValue(key, i)
            yield reg_entry(tree, path, n, v)
            i += 1
        except OSError:
            break ## Expected, this is how iteration ends.

def notify_windows(action, tree, path, varname, value):
    win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
    print("---%s %s" % (action, reg_entry(tree, path, varname, value)), file=sys.stderr)

def manage_registry_env_vars(varname=None, value=None):
    reg_keys = [
        ('HKEY_LOCAL_MACHINE', r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'),
        ('HKEY_CURRENT_USER', r'Environment'),
    ]
    for (tree_name, path) in reg_keys:
        tree = eval('winreg.%s'%tree_name)
        try:
            with winreg.ConnectRegistry(None, tree) as reg:
                with winreg.OpenKey(reg, path, 0, winreg.KEY_ALL_ACCESS) as key:
                    if not varname:
                        for regent in yield_all_entries(tree_name, path, key):
                            print(regent)
                    else:
                        if not value:
                            if varname.startswith('-'):
                                varname = varname[1:]
                                value = query_value(key, varname)
                                winreg.DeleteValue(key, varname)
                                notify_windows("Deleted", tree_name, path, varname, value)
                                break  ## Don't propagate into user-tree.
                            else:
                                value = query_value(key, varname)
                                print(reg_entry(tree_name, path, varname, value))
                        else:
                            if varname.startswith('+'):
                                varname = varname[1:]
                                value = query_value(key, varname) + ';' + value
                            winreg.SetValueEx(key, varname, 0, winreg.REG_EXPAND_SZ, value)
                            notify_windows("Updated", tree_name, path, varname, value)
                            break  ## Don't propagate into user-tree.
        except PermissionError as ex:
            print("!!!Cannot access %s due to: %s" % 
                    (reg_key(tree_name, path, varname), ex), file=sys.stderr)
        except FileNotFoundError as ex:
            print("!!!Cannot find %s due to: %s" % 
                    (reg_key(tree_name, path, varname), ex), file=sys.stderr)

if __name__=='__main__':
    args = sys.argv
    argc = len(args)
    if argc > 3:
        print(__doc__.format(prog=args[0]), file=sys.stderr)
        sys.exit()

    manage_registry_env_vars(*args[1:])

ด้านล่างนี้เป็นตัวอย่างการใช้งานโดยสมมติว่าได้บันทึกไว้ในไฟล์ที่เรียกว่าsetenv.pyที่ไหนสักแห่งในเส้นทางปัจจุบันของคุณ โปรดทราบว่าในตัวอย่างเหล่านี้ฉันไม่มีสิทธิ์ระดับผู้ดูแลระบบดังนั้นการเปลี่ยนแปลงจึงส่งผลต่อโครงสร้างรีจิสทรีของผู้ใช้ภายในเครื่องของฉันเท่านั้น:

> REM ## Print all env-vars
> setenv.py
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
HKEY_CURRENT_USER\Environment:PATH=...
...

> REM ## Query env-var:
> setenv.py PATH C:\foo
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
!!!Cannot find HKEY_CURRENT_USER\Environment:PATH due to: [WinError 2] The system cannot find the file specified

> REM ## Set env-var:
> setenv.py PATH C:\foo
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
---Set HKEY_CURRENT_USER\Environment:PATH=C:\foo

> REM ## Append env-var:
> setenv.py +PATH D:\Bar
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
---Set HKEY_CURRENT_USER\Environment:PATH=C:\foo;D:\Bar

> REM ## Delete env-var:
> setenv.py -PATH
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session   Manager\Environment:PATH due to: [WinError 5] Access is denied
---Deleted HKEY_CURRENT_USER\Environment:PATH

[*] ดัดแปลงจาก: http://code.activestate.com/recipes/416087-persistent-environment-variables-on-windows/


4

เพื่อวัตถุประสงค์ในการอ้างอิงสำหรับทุกคนที่ค้นหาวิธีเปลี่ยนเส้นทางด้วยรหัสฉันกำลังอ้างถึงโพสต์ที่มีประโยชน์โดยโปรแกรมเมอร์ Delphi จากหน้าเว็บนี้: http://www.tek-tips.com/viewthread.cfm?qid=686382

TonHu (Programmer) 22 ต.ค. 53 17:57 น. พบที่อ่านโพสต์ต้นฉบับที่นี่: http://news.jrsoftware.org/news/innosetup.isx/msg02129 ....

ข้อความที่ตัดตอนมาของสิ่งที่คุณต้องการคือ:

คุณต้องระบุสตริง "Environment" ใน LParam ใน Delphi คุณจะทำเช่นนี้:

 SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, Integer(PChar('Environment')));

ได้รับการแนะนำโดย Jordan Russell, http://www.jrsoftware.orgผู้เขียน (ao) InnoSetup ("Inno Setup เป็นโปรแกรมติดตั้งฟรีสำหรับโปรแกรม Windows เปิดตัวครั้งแรกในปี 1997 Inno Setup เป็นคู่แข่งกันในปัจจุบันและยังเหนือกว่าหลาย ๆ โปรแกรมติดตั้งเชิงพาณิชย์ในชุดคุณลักษณะและความเสถียร ") (ฉันแค่อยากให้มีคนใช้ InnoSetup มากขึ้น)

HTH


คุณต้องแก้ไขรีจิสทรี นอกจากนี้การส่งไปยังจำนวนเต็มยังไม่ดี ส่งเป็น LPARAM แทนสำหรับความเข้ากันได้ 64 บิต
David Heffernan

นี่คือตัวอย่างgithub.com/gilligan/snesdev/blob/1253994/tools/cc65-2.13.2/…

4

ในเครือข่ายขององค์กรที่ผู้ใช้เข้าถึงได้ จำกัด และใช้แอพพกพามีเคล็ดลับบรรทัดคำสั่งเหล่านี้:

  1. ค้นหาตัวแปร env ของผู้ใช้: reg query "HKEY_CURRENT_USER\Environment". ใช้"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"สำหรับ LOCAL_MACHINE
  2. เพิ่มตัวแปร env ผู้ใช้ใหม่: reg add "HKEY_CURRENT_USER\Environment" /v shared_dir /d "c:\shared" /t REG_SZ. ใช้REG_EXPAND_SZสำหรับเส้นทางที่มีตัวแปร %% อื่น ๆ
  3. ลบตัวแปร env ที่มีอยู่: reg delete "HKEY_CURRENT_USER\Environment" /v shared_dir.

3

คริปนี้ http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

รวมการเรียก Windows API ที่จำเป็นทั้งหมดซึ่งสามารถปรับโครงสร้างใหม่ได้ตามความต้องการของคุณ จริงๆแล้วมันเป็น AutoHotkey GUI เพื่อเปลี่ยน System PATH ได้อย่างง่ายดาย จำเป็นต้องเรียกใช้ในฐานะผู้ดูแลระบบ


อ่านคำถาม อีกครั้ง
jiggunjer

สคริปต์ที่ยอดเยี่ยม ฉันใช้ HotKey แต่ไม่รู้ว่าต้องทำอย่างไรหรือต้องทำอย่างไรเพื่อเพิ่มสคริปต์เข้าไป คุณสามารถให้ความช่วยเหลือเสนอลิงค์หรืออธิบายสิ่งที่ต้องทำได้หรือไม่?
jwzumwalt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.