Eryk Sun added the comment:

As is documented for CreateProcess [1], the search path always includes the 
following directories:

    * The directory from which the application loaded.
    * The current directory for the parent process.
    * The Windows system directory. Use the
      GetSystemDirectory function to get the path of
      this directory.
    * The 16-bit Windows system directory. There is no
      function that obtains the path of this directory,
      but it is searched. The name of this directory is
      System.
    * The Windows directory. Use the GetWindowsDirectory
      function to get the path of this directory.
    * The directories that are listed in the PATH
      environment variable.

The value of PATH comes from the calling process environment, not from the 
environment passed in the lpEnvironment parameter. If you need to search some 
other list of paths, you can use shutil.which to find the fully qualified path 
of the target executable.

Note that in Vista+ you can remove the current directory from the search list 
by defining the environment variable "NoDefaultCurrentDirectoryInExePath" [2]. 

The following examples show the minimum search path that CreateProcess uses 
when PATH isn't defined.

    >>> 'PATH' in os.environ
    False

    >>> subprocess.call('python -Sc "import sys; print(sys.prefix)"')
    Breakpoint 0 hit
    KERNELBASE!SearchPathW:
    00007ff9`cf4b5860 488bc4          mov     rax,rsp
    0:000> du @rcx
    0000006c`a7074410  "C:\Program Files\Python35;.;C:\W"
    0000006c`a7074450  "indows\SYSTEM32\;C:\Windows\syst"
    0000006c`a7074490  "em;C:\Windows"
    0:000> g
    C:\Program Files\Python35
    0

    >>> os.environ['NoDefaultCurrentDirectoryInExePath'] = '1'

    >>> subprocess.call('python -Sc "import sys; print(sys.prefix)"')
    Breakpoint 0 hit
    KERNELBASE!SearchPathW:
    00007ff9`cf4b5860 488bc4          mov     rax,rsp
    0:000> du @rcx
    0000006c`a6560710  "C:\Program Files\Python35;C:\Win"
    0000006c`a6560750  "dows\SYSTEM32\;C:\Windows\system"
    0000006c`a6560790  ";C:\Windows"
    0:000> g
    C:\Program Files\Python35
    0

Note that in the 2nd case the current directory ('.') is no longer present 
between the application directory ("C:\Program Files\Python35") and the system 
directory ("C:\Windows\SYSTEM32\").

CreateProcess executes PE executables and batch files (run via the %ComSpec% 
interpreter). It automatically appends the .exe extension when searching for an 
executable. It does this via the lpExtension parameter of SearchPath [3]. 

Some .com files are PE executables (e.g. chcp.com). Otherwise it's not really 
usefully to loop over the PATHEXT extensions unless you're using shell=True, 
since most are filetypes that CreateProcess doesn't support [4]. 

[1]: https://msdn.microsoft.com/en-us/library/ms682425
[2]: https://msdn.microsoft.com/en-us/library/ms684269
[3]: https://msdn.microsoft.com/en-us/library/aa365527
[4]: If Microsoft's Windows team cared at all about cross-platform
     idioms they'd add shebang support to CreateProcess, which
     would make all scripts, not just batch files, directly
     executable without requiring ShellExecuteEx and registered
     filetypes. ShellExecuteEx doesn't support a lot of useful
     creation flags that are only available by calling
     CreateProcess directly, and it also doesn't check ACLs to
     prevent executing a file. So scripts are second class
     citizens in Windows, which is why Python has to embed 
     scripts in .exe wrappers.

----------
nosy: +eryksun

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue8557>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to