runproc.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. '''runproc.py
  2. start a process with three inherited pipes.
  3. Try to write to and read from those.
  4. '''
  5. import win32api
  6. import win32pipe
  7. import win32file
  8. import win32process
  9. import win32security
  10. import win32con
  11. import msvcrt
  12. import os
  13. class Process:
  14. def run(self, cmdline):
  15. # security attributes for pipes
  16. sAttrs = win32security.SECURITY_ATTRIBUTES()
  17. sAttrs.bInheritHandle = 1
  18. # create pipes
  19. hStdin_r, self.hStdin_w = win32pipe.CreatePipe(sAttrs, 0)
  20. self.hStdout_r, hStdout_w = win32pipe.CreatePipe(sAttrs, 0)
  21. self.hStderr_r, hStderr_w = win32pipe.CreatePipe(sAttrs, 0)
  22. # set the info structure for the new process.
  23. StartupInfo = win32process.STARTUPINFO()
  24. StartupInfo.hStdInput = hStdin_r
  25. StartupInfo.hStdOutput = hStdout_w
  26. StartupInfo.hStdError = hStderr_w
  27. StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES
  28. # Mark doesn't support wShowWindow yet.
  29. # StartupInfo.dwFlags = StartupInfo.dwFlags | win32process.STARTF_USESHOWWINDOW
  30. # StartupInfo.wShowWindow = win32con.SW_HIDE
  31. # Create new output read handles and the input write handle. Set
  32. # the inheritance properties to FALSE. Otherwise, the child inherits
  33. # the these handles; resulting in non-closeable handles to the pipes
  34. # being created.
  35. pid = win32api.GetCurrentProcess()
  36. tmp = win32api.DuplicateHandle(
  37. pid,
  38. self.hStdin_w,
  39. pid,
  40. 0,
  41. 0, # non-inheritable!!
  42. win32con.DUPLICATE_SAME_ACCESS)
  43. # Close the inhertible version of the handle
  44. win32file.CloseHandle(self.hStdin_w)
  45. self.hStdin_w = tmp
  46. tmp = win32api.DuplicateHandle(
  47. pid,
  48. self.hStdout_r,
  49. pid,
  50. 0,
  51. 0, # non-inheritable!
  52. win32con.DUPLICATE_SAME_ACCESS)
  53. # Close the inhertible version of the handle
  54. win32file.CloseHandle(self.hStdout_r)
  55. self.hStdout_r = tmp
  56. # start the process.
  57. hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(
  58. None, # program
  59. cmdline,# command line
  60. None, # process security attributes
  61. None, # thread attributes
  62. 1, # inherit handles, or USESTDHANDLES won't work.
  63. # creation flags. Don't access the console.
  64. 0, # Don't need anything here.
  65. # If you're in a GUI app, you should use
  66. # CREATE_NEW_CONSOLE here, or any subprocesses
  67. # might fall victim to the problem described in:
  68. # KB article: Q156755, cmd.exe requires
  69. # an NT console in order to perform redirection..
  70. None, # no new environment
  71. None, # current directory (stay where we are)
  72. StartupInfo)
  73. # normally, we would save the pid etc. here...
  74. # Child is launched. Close the parents copy of those pipe handles
  75. # that only the child should have open.
  76. # You need to make sure that no handles to the write end of the
  77. # output pipe are maintained in this process or else the pipe will
  78. # not close when the child process exits and the ReadFile will hang.
  79. win32file.CloseHandle(hStderr_w)
  80. win32file.CloseHandle(hStdout_w)
  81. win32file.CloseHandle(hStdin_r)
  82. self.stdin = os.fdopen(msvcrt.open_osfhandle(self.hStdin_w, 0), "wb")
  83. self.stdin.write('hmmmmm\r\n')
  84. self.stdin.flush()
  85. self.stdin.close()
  86. self.stdout = os.fdopen(msvcrt.open_osfhandle(self.hStdout_r, 0), "rb")
  87. print("Read on stdout: ", repr(self.stdout.read()))
  88. self.stderr = os.fdopen(msvcrt.open_osfhandle(self.hStderr_r, 0), "rb")
  89. print("Read on stderr: ", repr(self.stderr.read()))
  90. if __name__ == '__main__':
  91. p = Process()
  92. exe = win32api.GetModuleFileName(0)
  93. p.run(exe + ' cat.py')
  94. # end of runproc.py