Interface for modifying Windows environment variables from Python

后端 未结 6 1949
无人共我
无人共我 2020-12-08 05:01

How can I persistently modify the Windows environment variables from a Python script? (it\'s the setup.py script)

I\'m looking for a standard function or module to u

6条回答
  •  情话喂你
    2020-12-08 06:03

    This Python-script[*] attempts to modify the GLOBAL env-vars in registry, if no-permissions falls-back to user's registry, and then notifies all windows about the change:

    """
    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 show_all(tree, path, key):
        i = 0
        while True:
            try:
                n,v,t = winreg.EnumValue(key, i)
                print(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)))
    
    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:
                            show_all(tree_name, path, key)
                        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))
            except FileNotFoundError as ex:
                print("!!!Cannot find %s due to: %s" % 
                        (reg_key(tree_name, path, varname), ex))
    
    if __name__=='__main__':
        args = sys.argv
        argc = len(args)
        if argc > 3:
            print(__doc__.format(prog=args[0]))
            sys.exit()
    
        manage_registry_env_vars(*args[1:])
    

    Below are some usage examples, assuming it has been saved in a file called setenv.py somewhere in your current path. Note that in these examples i didn't have admin-rights, so the changes affected only my local user's registry tree:

    > 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
    

    [*] Adapted from: http://code.activestate.com/recipes/416087-persistent-environment-variables-on-windows/

提交回复
热议问题