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


Groups > comp.lang.python > #102991 > unrolled thread

extending PATH on Windows?

Started byUlli Horlacher <framstag@rus.uni-stuttgart.de>
First post2016-02-16 08:30 +0000
Last post2016-02-16 07:17 -0600
Articles 8 on this page of 28 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  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

Page 2 of 2 — ← Prev page 1 [2]


#103205

Frompyotr filipivich <phamp@mindspring.com>
Date2016-02-19 09:04 -0800
Message-ID<jeiecbhv61eji4t5i0b5uknj54hqvfr09a@4ax.com>
In reply to#103180
Ulli Horlacher <framstag@rus.uni-stuttgart.de> on Fri, 19 Feb 2016
10:42:52 +0000 (UTC) typed in comp.lang.python  the following:
>pyotr filipivich <phamp@mindspring.com> wrote:
>
>> >       Windows (especially 7) search function is highly crippled. There is
>> >some command sequence that will open it up to looking at other file types
>> >and locations.
>> >
>> >http://answers.microsoft.com/en-us/windows/forum/windows_7-files/windows-7-search-does-not-find-files-that-it/61b88d5e-7df7-4427-8a2e-82b801a4a746?auth=1
>> 
>> 
>> Thanks.  I've found it "simpler" to just open a command prompt, and
>> use DOS.
>
>How can one search for files with DOS?

cd %searchPathStart%
dir /s *.php
or variants.
-- 
pyotr filipivich
Next month's Panel: Graft - Boon or blessing?

[toc] | [prev] | [next] | [standalone]


#103209

Fromeryk sun <eryksun@gmail.com>
Date2016-02-19 12:04 -0600
Message-ID<mailman.55.1455905118.2289.python-list@python.org>
In reply to#103180
On Fri, Feb 19, 2016 at 4:48 AM, Chris Angelico <rosuav@gmail.com> wrote:
> On Fri, Feb 19, 2016 at 9:42 PM, Ulli Horlacher
> <framstag@rus.uni-stuttgart.de> wrote:
>> pyotr filipivich <phamp@mindspring.com> wrote:
>>
>>> >       Windows (especially 7) search function is highly crippled. There is
>>> >some command sequence that will open it up to looking at other file types
>>> >and locations.
>>> >
>>> >http://answers.microsoft.com/en-us/windows/forum/windows_7-files/windows-7-search-does-not-find-files-that-it/61b88d5e-7df7-4427-8a2e-82b801a4a746?auth=1
>>>
>>>
>>> Thanks.  I've found it "simpler" to just open a command prompt, and
>>> use DOS.
>>
>> How can one search for files with DOS?
>
> dir /s /b \*add2path.*

This search is carried out by Windows NT instead of MS-DOS in almost
all cases nowadays:

    Z:\Python\repo\2.7>dir /s /b Tools\Scripts\win_add?*.*
    Breakpoint 0 hit
    ntdll!NtQueryDirectoryFile:
    00007ffb`d9d138c0 4c8bd1          mov     r10,rcx

    0:000> dS poi(@rsp + a*8)
    000000df`bab1ff9a  "win_add><"*"

NT has normal (i.e. sane) * and ? wildcard matching, so WinAPI
FindFirstFile has to translate DOS wildcards to special values before
calling NtQueryDirectoryFile. See the file-system runtime library
function FsRtlIsNameInExpression [1]. Dot, question mark, and asterisk
may be mapped (depending on context in the string) to double quote and
the angle brackets, as shown in the above debugger output in which
'win_add?*.*' is passed to the system call as 'win_add><"*'.

    DOS_DOT (")
    Matches either a period or zero characters beyond the
    name string.

    DOS_QM (>)
    Matches any single character or, upon encountering a
    period or end of name string, advances the expression
    to the end of the set of contiguous DOS_QMs.

    DOS_STAR (<)
    Matches zero or more characters until encountering
    and matching the final . in the name.

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

[toc] | [prev] | [next] | [standalone]


#103219

Fromeryk sun <eryksun@gmail.com>
Date2016-02-19 12:42 -0600
Message-ID<mailman.59.1455907410.2289.python-list@python.org>
In reply to#103180
On Fri, Feb 19, 2016 at 8:18 AM, Gisle Vanem <gvanem@yahoo.no> wrote:
> Dennis Lee Bieber wrote:
>
>>>> How can one search for files with DOS?
>>>
>>> dir /s /b \*add2path.*
>>>
>>> ChrisA
>>
>>       Or move to PowerShell...
>>
>> Windows PowerShell
>> Copyright (C) 2009 Microsoft Corporation. All rights reserved.
>>
>> PS C:\Users\Wulfraed\Documents> Get-ChildItem -Path c:\ -Filter *add2path*
>> -Name -Recurse
>
> Clumsy IMHO. Try:
> c:\> envtool --path *ipython*
>
> Matches in %PATH:

Your tool has special integration with Python's search paths, which is
cool. But for someone that wants some of these features without
installing another program and without learning PowerShell, where.exe
may suffice:

    https://technet.microsoft.com/en-us/library/cc753148

Search PATH and the current directory:

    C:\>where kd
    C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\kd.exe

Search an environment variable that may contain one or more directories:

    C:\>set MYPATH=^
    More? %SystemRoot%\System32;^
    More? %SystemRoot%\System32\drivers

    C:\>where $MYPATH:conhost*.*
    C:\Windows\System32\conhost.exe
    C:\Windows\System32\ConhostV1.dll
    C:\Windows\System32\ConhostV2.dll

Search a list of directories:

    C:\>where "%MYPATH%":con*.sys
    C:\Windows\System32\drivers\condrv.sys

Recursively search a directory:

    C:\>where /r "%LocalAppData%\Programs" python.exe
    C:\Users\Administrator\AppData\Local\Programs\Python\
        Python35-32\python.exe

[toc] | [prev] | [next] | [standalone]


#103228

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2016-02-19 19:57 -0500
Message-ID<mailman.7.1455929888.13884.python-list@python.org>
In reply to#103180
On Fri, 19 Feb 2016 12:42:41 -0600, eryk sun <eryksun@gmail.com> declaimed
the following:


>Your tool has special integration with Python's search paths, which is
>cool. But for someone that wants some of these features without
>installing another program and without learning PowerShell, where.exe
>may suffice:
>
>    https://technet.microsoft.com/en-us/library/cc753148
>
>Search PATH and the current directory:
>
>    C:\>where kd
>    C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\kd.exe
>

	Problem -- if the OP's PATH had contained the location of the add2path
script, the OP might not have needed to search for it... (presuming their
configuration also was set up to treat .py files as executable, entering
win_add2path would be all that was needed to run it on a command line)

	"where" only searches the locations defined in PATH; the PowerShell
(and the old command prompt equivalent) would find the file regardless of
where it is (on the partition). It, therefore, won't find copies that are
in other locations.
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#103264

Fromeryk sun <eryksun@gmail.com>
Date2016-02-20 07:31 -0600
Message-ID<mailman.27.1455975160.13884.python-list@python.org>
In reply to#103180
On Fri, Feb 19, 2016 at 6:57 PM, Dennis Lee Bieber
<wlfraed@ix.netcom.com> wrote:
>
>         Problem -- if the OP's PATH had contained the location of the add2path
> script, the OP might not have needed to search for it... (presuming their
> configuration also was set up to treat .py files as executable, entering
> win_add2path would be all that was needed to run it on a command line)

Ulli didn't need to run the file, but to read it as example code.

>         "where" only searches the locations defined in PATH

I made it clear in several examples that where.exe is not limited to
searching PATH.

[toc] | [prev] | [next] | [standalone]


#103112

Fromeryk sun <eryksun@gmail.com>
Date2016-02-18 06:54 -0600
Message-ID<mailman.248.1455800105.22075.python-list@python.org>
In reply to#103058
On Wed, Feb 17, 2016 at 6:53 PM, Dennis Lee Bieber
<wlfraed@ix.netcom.com> wrote:
> On Wed, 17 Feb 2016 17:49:11 +0000 (UTC), Ulli Horlacher
> <framstag@rus.uni-stuttgart.de> declaimed the following:
>
>>Thorsten Kampe <thorsten@thorstenkampe.de> wrote:
>>
>>> By the way: there is a script called `win_add2path.py` in your Python
>>> distribution
>>
>>I have
>>"Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec  5 2015, 20:32:19) [MSC
>>v.1500 32 bit (Intel)] on win32"
>>and there is no "win_add2path.py"
>>
> C:\Python_x64\Python27\Tools\scripts\win_add2path.py
>
> PythonWin 2.7.5 (default, Sep 16 2013, 23:11:01) [MSC v.1500 64 bit
> (AMD64)] on win32.
> Portions Copyright 1994-2008 Mark Hammond - see 'Help/About PythonWin' for
> further copyright information.
>
> But I can't confirm that this is not something added in the ActiveState
> release.

It's here:
https://hg.python.org/cpython/file/v2.7.11/Tools/scripts/win_add2path.py

But there are a few issues with this script.

* A default value of u"%PATH%" is wrong. That causes the system
  PATH to be concatenated with itself.

* For the user scripts directory, replacing appdata with
  "%APPDATA%" causes os.path.isdir to always fail.

* For QueryValueEx, the only error it should handle is
  ERROR_FILE_NOT_FOUND. Other OS errors are unlikely, but they
  shouldn't be masked.

* In Python 2, the value returned by QueryValueEx is a unicode
  string, which this script assumes is ASCII only. So it could
  die on a UnicodeDecodeError.

* REG_EXPAND_SZ should only be used when '%' occurs 2 or more
  times. Otherwise use REG_SZ. This is important for two-pass
  environment variable expansion. Thus an existing REG_SZ type
  should be preserved, if that's reasonable, because the user may be
  reusing PATH in a  REG_EXPAND_SZ variable.

* It doesn't broadcast a WM_SETTINGCHANGE message, so it
  needlessly forces the user to log off and back on in order to
  use the modified PATH.

Here's a new version for Python 2. I generalized the shell-variable
replacement to a list of well-known folders.

    import os
    import sys
    import site
    import ctypes
    import _winreg
    import warnings

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

    HWND_BROADCAST = 0xFFFF
    WM_SETTINGCHANGE = 0x001A
    SMTO_ABORTIFHUNG = 0x0002
    ERROR_FILE_NOT_FOUND = 0x0002
    ERROR_TIMEOUT = 0x05B4
    HKCU = _winreg.HKEY_CURRENT_USER

    ENVIRONMENT = u"Environment"
    PATH = u"PATH"
    SCRIPTS = u"Scripts"

    dir_vars = [u"%APPDATA%",
                u"%LOCALAPPDATA%",
                u"%USERPROFILE%",
                u"%HOMEDRIVE%%HOMEPATH%",
                u"%ProgramFiles%",
                u"%ProgramFiles(x86)%"]

    dir_vals = [_winreg.ExpandEnvironmentStrings(v) for v in dir_vars]

    def broadcast_change(lparam):
        if not user32.SendMessageTimeoutW(
                        HWND_BROADCAST, WM_SETTINGCHANGE,
                        0, ctypes.c_wchar_p(lparam),
                        SMTO_ABORTIFHUNG, 1000, None):
            err = ctypes.get_last_error()
            if err != ERROR_TIMEOUT:
                raise ctypes.WinError(err)

    def modify():
        executable = sys.executable.decode("mbcs")
        pythonpath = os.path.dirname(os.path.normpath(executable))
        scripts = os.path.join(pythonpath, SCRIPTS)
        if hasattr(site, "USER_SITE"):
            userpath = site.USER_SITE.decode("mbcs")
            userscripts = os.path.join(userpath, SCRIPTS)
        else:
            userscripts = None
        with _winreg.CreateKey(HKCU, ENVIRONMENT) as key:
            try:
                envpath, dtype = _winreg.QueryValueEx(key, PATH)
            except WindowsError as e:
                if e.winerror != ERROR_FILE_NOT_FOUND:
                    raise
                envpath, dtype = u"", _winreg.REG_EXPAND_SZ
            if dtype not in (_winreg.REG_SZ, _winreg.REG_EXPAND_SZ):
                raise TypeError(r"Existing PATH value is not a string.")
            if dtype == _winreg.REG_SZ and envpath.count(u"%") > 1:
                warnings.warn('Changing type to REG_EXPAND_SZ.')
                dtype = _winreg.REG_EXPAND_SZ
            paths = [envpath]
            for path in (pythonpath, scripts, userscripts):
                if path and path not in envpath and os.path.isdir(path):
                    if dtype == _winreg.REG_EXPAND_SZ:
                        for var, val in zip(dir_vars, dir_vals):
                            if val in path:
                                path = path.replace(val, var)
                                break
                        if path in envpath:
                            continue
                    paths.append(path)
            envpath = os.pathsep.join(paths)
            _winreg.SetValueEx(key, PATH, 0, dtype, envpath)
        broadcast_change(ENVIRONMENT)
        return paths, envpath

    def main():
        paths, envpath = modify()
        if len(paths) > 1:
            print "Path(s) added:"
            print '\n'.join(paths[1:])
        else:
            print "No path was added"
        print "\nCurrent user PATH is now:\n%s\n" % envpath
        print "Expanded:"
        print _winreg.ExpandEnvironmentStrings(envpath)

    if __name__ == '__main__':
        main()

[toc] | [prev] | [next] | [standalone]


#103136

FromUlli Horlacher <framstag@rus.uni-stuttgart.de>
Date2016-02-18 16:50 +0000
Message-ID<na4sp8$skl$2@news2.informatik.uni-stuttgart.de>
In reply to#103112
eryk sun <eryksun@gmail.com> wrote:


> https://hg.python.org/cpython/file/v2.7.11/Tools/scripts/win_add2path.py
> 
> But there are a few issues with this script.

(... lot of flaws ...)

> Here's a new version for Python 2. I generalized the shell-variable
> replacement to a list of well-known folders.

Great script, I will save it for later usage!

But in the meantime I came to another solution:
Instead of modifying PATH systemwide, I modify it only for cmd.exe.

To achieve this, I set the registry key
"HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun"
to "%USERPROFILE%\autorun.cmd" and write in this file:
set PATH=%PATH%;%USERPROFILE%\Desktop

If there was already an old value in
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
it will be saved to %USERPROFILE%\autorun.cmd, too

This autorun.cmd is like .bashrc on UNIX.

-- 
Ullrich Horlacher              Server und Virtualisierung
Rechenzentrum IZUS/TIK         E-Mail: horlacher@tik.uni-stuttgart.de
Universitaet Stuttgart         Tel:    ++49-711-68565868
Allmandring 30a                Fax:    ++49-711-682357
70550 Stuttgart (Germany)      WWW:    http://www.tik.uni-stuttgart.de/

[toc] | [prev] | [next] | [standalone]


#103004

Fromeryk sun <eryksun@gmail.com>
Date2016-02-16 07:17 -0600
Message-ID<mailman.165.1455628688.22075.python-list@python.org>
In reply to#102991
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)

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.python


csiph-web