Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #103004

Re: extending PATH on Windows?

From eryk sun <eryksun@gmail.com>
Newsgroups comp.lang.python
Subject Re: extending PATH on Windows?
Date 2016-02-16 07:17 -0600
Message-ID <mailman.165.1455628688.22075.python-list@python.org> (permalink)
References <n9umo3$9lg$1@news2.informatik.uni-stuttgart.de>

Show all headers | View raw


On Tue, Feb 16, 2016 at 2:30 AM, Ulli Horlacher
<framstag@rus.uni-stuttgart.de> wrote:
>
> So far, I use:
>
>    system('setx PATH "%PATH%;'+bindir+'"')
>
> The problem: In a new process (cmd.exe) PATH contains a lot of double
> elements. As far as I have understood, Windows builds the PATH
> environment variable from a system component and a user component. With
> the setx command from above I have copied the system PATH into the user
> PATH component.

setx broadcasts a WM_SETTINGCHANGE [1] message that notifies Explorer
to reload its environment from the registry, so the user doesn't have
to start a new session. It also decides whether to use REG_SZ or
REG_EXPAND_SZ depending on the presence of mutliple "%" characters in
the string.

[1]: https://msdn.microsoft.com/en-us/library/ms725497

But as you note it's no good for extending an existing value,
especially not for PATH or a value that references other "%variables%"
that you want to remain unexpanded. To do this right, you have to at
least use winreg to query the user's PATH value from the registry. But
then you may as well replace setx completely. Here's a little
something to get you started.

    import os
    import sys
    import types
    import ctypes

    user32 = ctypes.WinDLL('user32', use_last_error=True)

    try:
        import winreg
    except ImportError:
        import _winreg as winreg

    def extend_path(new_paths, persist=True):
        if isinstance(new_paths, getattr(types, 'StringTypes', str)):
            new_paths = [new_paths]
        new_paths = [os.path.abspath(p) for p in new_paths]
        paths = [p for p in os.environ.get('PATH', '').split(os.pathsep) if p]
        for p in new_paths:
            if p not in paths:
                paths.append(p)
        os.environ['PATH'] = os.pathsep.join(paths)
        if persist:
            _persist_path(new_paths)

    def _persist_path(new_paths):
        if sys.version_info[0] == 2:
            temp_paths = []
            for p in new_paths:
                if isinstance(p, unicode):
                    temp_paths.append(p)
                else:
                    temp_paths.append(p.decode('mbcs'))
            new_paths = temp_paths
        with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                            'Environment', 0,
                            winreg.KEY_QUERY_VALUE |
                            winreg.KEY_SET_VALUE) as hkey:
            try:
                user_path, dtype = winreg.QueryValueEx(hkey, 'PATH')
            except WindowsError as e:
                ERROR_FILE_NOT_FOUND = 0x0002
                if e.winerror != ERROR_FILE_NOT_FOUND:
                    raise
                paths = []
            else:
                if dtype in (winreg.REG_SZ, winreg.REG_EXPAND_SZ):
                    paths = [p for p in user_path.split(os.pathsep) if p]
                else:
                    paths = []
            for p in new_paths:
                if p not in paths:
                    paths.append(p)
            pathstr = os.pathsep.join(paths)
            if pathstr.count('%') < 2:
                dtype = winreg.REG_SZ
            else:
                dtype = winreg.REG_EXPAND_SZ
            winreg.SetValueEx(hkey, 'PATH', 0, dtype, pathstr)
        _broadcast_change(u'Environment')

    def _broadcast_change(lparam):
        HWND_BROADCAST   = 0xFFFF
        WM_SETTINGCHANGE = 0x001A
        SMTO_ABORTIFHUNG = 0x0002
        ERROR_TIMEOUT = 0x05B4
        wparam = 0
        if not user32.SendMessageTimeoutW(
                        HWND_BROADCAST, WM_SETTINGCHANGE,
                        wparam, ctypes.c_wchar_p(lparam),
                        SMTO_ABORTIFHUNG, 1000, None):
            err = ctypes.get_last_error()
            if err != ERROR_TIMEOUT:
                raise ctypes.WinError(err)

Back to comp.lang.python | Previous | NextPrevious in thread | Find similar | Unroll thread


Thread

extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-16 08:30 +0000
  Re: extending PATH on Windows? Thorsten Kampe <thorsten@thorstenkampe.de> - 2016-02-16 13:19 +0100
    Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-16 12:38 +0000
      Re: extending PATH on Windows? Thorsten Kampe <thorsten@thorstenkampe.de> - 2016-02-16 14:38 +0100
      Re: extending PATH on Windows? Thorsten Kampe <thorsten@thorstenkampe.de> - 2016-02-16 14:43 +0100
        Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-17 17:49 +0000
          Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-17 13:02 -0600
            Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-17 20:29 +0000
              Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-17 15:17 -0600
                Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-17 22:37 +0000
                Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-18 16:55 +0000
                Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-19 12:07 -0600
          Re: extending PATH on Windows? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2016-02-17 19:53 -0500
            Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-18 16:24 +0000
              Re: extending PATH on Windows? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2016-02-18 21:57 -0500
                Re: extending PATH on Windows? pyotr filipivich <phamp@mindspring.com> - 2016-02-18 19:39 -0800
                Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-19 10:42 +0000
                Re: extending PATH on Windows? Chris Angelico <rosuav@gmail.com> - 2016-02-19 21:48 +1100
                Re: extending PATH on Windows? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2016-02-19 07:45 -0500
                Re: extending PATH on Windows? Gisle Vanem <gvanem@yahoo.no> - 2016-02-19 15:18 +0100
                Re: extending PATH on Windows? pyotr filipivich <phamp@mindspring.com> - 2016-02-19 09:04 -0800
                Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-19 12:04 -0600
                Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-19 12:42 -0600
                Re: extending PATH on Windows? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2016-02-19 19:57 -0500
                Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-20 07:31 -0600
          Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-18 06:54 -0600
            Re: extending PATH on Windows? Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2016-02-18 16:50 +0000
  Re: extending PATH on Windows? eryk sun <eryksun@gmail.com> - 2016-02-16 07:17 -0600

csiph-web