do anonymous pipes normally work on NT?

Bill Tutt billtut at microsoft.com
Sat Jun 19 18:51:11 EDT 1999


After digging through this stuff, I went back and looked at the code I had
written for win32popen.cpp. I realized that I had forgotten why I had
written the DuplicateHandle() code, so I went back commented it out from the
KB article that I had originally used, and then modified runproc.py to do
the same thing.

cat.py is now much happier with life with the new and improved runproc.py.
The other important thing is to remember to close the stdin writing handle
only once.
Once you call msvcrt.open_osfhandle, you don't need to call
win32file.CloseHandle on it any more, simply issue a CRT close, and all will
be well.

Notice I also changed the DETACHED_PROCESS to a zero. This is to not do
those wierd things that DETACHED_PROCESS seems to do. Since stdin, etc.. are
pipes, it doesn't matter if the process technically has access to
runproc.py's NT console. (if any)

The other alternative from 0 would be to pass in CREATE_NEW_CONSOLE, and
tweak win32process_win32module.cpp to add:
	{"wShowWindow",	     T_INT,  OFF(m_startupinfo.wShowWindow)},
//@prop integer|wShowWindow|

onto the end of PySTARTUPINFO::memberlist, and then do the following:
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdInput  = hStdin_r
        StartupInfo.hStdOutput = hStdout_w
        StartupInfo.hStdError  = hStderr_w
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES | 
		win32process.STARTF_USESHOWWINDOW
	  StartupInfo.wShowWindow = win32con.SW_HIDE

Mark: please add that line when you get a chance. :)

Bill

'''runproc.py

start a process with three inherited pipes.
Try to write to and read from those.
'''

import win32api
import win32pipe
import win32file
import win32process
import win32security
import win32con
import msvcrt
import os

class Process:
    def run(self, cmdline):
        # security attributes for pipes
        sAttrs = win32security.SECURITY_ATTRIBUTES()
        sAttrs.bInheritHandle = 1

        # create pipes
        hStdin_r,  self.hStdin_w  = win32pipe.CreatePipe(sAttrs, 0)
        self.hStdout_r, hStdout_w = win32pipe.CreatePipe(sAttrs, 0)
        self.hStderr_r, hStderr_w = win32pipe.CreatePipe(sAttrs, 0)

        # set the info structure for the new process.
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdInput  = hStdin_r
        StartupInfo.hStdOutput = hStdout_w
        StartupInfo.hStdError  = hStderr_w
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES
        
        # Create new output read handles and the input write handle. Set
        # the inheritance properties to FALSE. Otherwise, the child inherits
        # the these handles; resulting in non-closeable handles to the pipes
        # being created.
        pid = win32api.GetCurrentProcess()

        tmp = win32api.DuplicateHandle(
            pid,
            self.hStdin_w,
            pid,
            0,
            0,     # non-inheritable!!
            win32con.DUPLICATE_SAME_ACCESS)
        # Close the inhertible version of the handle
        win32file.CloseHandle(self.hStdin_w)
        self.hStdin_w = tmp
        tmp = win32api.DuplicateHandle(
            pid,
            self.hStdout_r,
            pid,
            0,
            0,     # non-inheritable!
            win32con.DUPLICATE_SAME_ACCESS)
        # Close the inhertible version of the handle
        win32file.CloseHandle(self.hStdout_r)
        self.hStdout_r = tmp

        # start the process.
        hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(
                None,   # program
                cmdline,# command line
                None,   # process security attributes
                None,   # thread attributes
                1,      # inherit handles, or USESTDHANDLES won't work.
                        # creation flags. Don't access the console.
                0,
                None,   # no new environment
                None,   # current directory (stay where we are)
                StartupInfo)
        # normally, we would save the pid etc. here...

        # Child is launched. Close the parents copy of those pipe handles
        # that only the child should have open.
        # You need to make sure that no handles to the write end of the
        # output pipe are maintained in this process or else the pipe will
        # not close when the child process exits and the ReadFile will hang.
        win32file.CloseHandle(hStderr_w)
        win32file.CloseHandle(hStdout_w)
        win32file.CloseHandle(hStdin_r)

        self.stdin = os.fdopen(msvcrt.open_osfhandle(self.hStdin_w, 0),
"wb")
        self.stdin.write('hmmmmm\n')
        self.stdin.flush()
        self.stdin.close()

        self.stdout = os.fdopen(msvcrt.open_osfhandle(self.hStdout_r, 0),
"rb")
        print "Read on stdout: ", repr(self.stdout.read())

        self.stderr = os.fdopen(msvcrt.open_osfhandle(self.hStderr_r, 0),
"rb")
        print "Read on stderr: ", repr(self.stderr.read())
        

if __name__ == '__main__':
    p = Process()
    p.run(r'd:\pythondevtree\python\dist\src\pcbuild\python_d.exe
d:\cat.py')

# end of runproc.py





More information about the Python-list mailing list