Currently I try to create an unit test which opens a file (with the corresponding application) and then the test-run should wait until the program is closed.
From the docs:
startfile() returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve the application’s exit status.
If you know the path of the application to open the file with, you could use subprocess.Popen() which allows for you to wait.
See: http://docs.python.org/library/os.html#os.startfile
http://docs.python.org/library/subprocess.html#subprocess.Popen
os.startfile
is, of course, completely non-blocking with no options to wait.
I'd recommend using the subprocess module, calling the Windows "start" command to open the file with the associated object, which does the same thing as os.startfile
, but allows you to wait for the process to finish.
e.g.:
subprocess.call(["start", my_file])
The documentation of os.startfile
explicitly says:
startfile() returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve the application’s exit status
So, I recommend using an alternative method, such as launching it via subprocess.Popen
, which does allow you to wait until the sub-process finishes.
answer = raw_input("Please Edit this file (done): ")
if answer == done:
blablabla
else:
stop programm or whatever
just let him tell you when he is done, simplest way i can imagine
You can call the underlying windows APIs, as recommended in this C++ answer, either via pywin32
:
def start_file_wait(fname):
import win32con
import win32api
import win32event
from win32com.shell import shellcon
from win32com.shell.shell import ShellExecuteEx
rc = ShellExecuteEx(
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
nShow=win32con.SW_SHOW,
lpFile=fname)
hproc = rc['hProcess']
win32event.WaitForSingleObject(hproc, win32event.INFINITE)
win32api.CloseHandle(hproc)
or directly from ctypes
:
def startfile_wait(fname):
import ctypes
from ctypes.wintypes import ULONG, DWORD, HANDLE, HKEY, HINSTANCE, HWND, LPCWSTR
class SHELLEXECUTEINFOW(ctypes.Structure):
_fields_ = [
("cbSize", DWORD),
("fMask", ULONG),
("hwnd", HWND),
("lpVerb", LPCWSTR),
("lpFile", LPCWSTR),
("lpParameters", LPCWSTR),
("lpDirectory", LPCWSTR),
("nShow", ctypes.c_int),
("hInstApp", HINSTANCE),
("lpIDList", ctypes.c_void_p),
("lpClass", LPCWSTR),
("hkeyClass", HKEY),
("dwHotKey", DWORD),
("DUMMYUNIONNAME", ctypes.c_void_p),
("hProcess", HANDLE)
]
shell_execute_ex = ctypes.windll.shell32.ShellExecuteExW
shell_execute_ex.argtypes = [ctypes.POINTER(SHELLEXECUTEINFOW)]
shell_execute_ex.res_type = ctypes.c_bool
wait_for_single_object = ctypes.windll.kernel32.WaitForSingleObject
wait_for_single_object.argtypes = [HANDLE, DWORD]
wait_for_single_object.res_type = DWORD
close_handle = ctypes.windll.kernel32.CloseHandle
close_handle.argtypes = [HANDLE]
close_handle.res_type = bool
# https://stackoverflow.com/a/17638969/102441
arg = SHELLEXECUTEINFOW()
arg.cbSize = ctypes.sizeof(arg)
arg.fMask = 0x00000040 # SEE_MASK_NOCLOSEPROCESS
arg.hwnd = None
arg.lpVerb = None
arg.lpFile = fname
arg.lpParameters = ""
arg.lpDirectory = None
arg.nShow = 10 # SW_SHOWDEFAULT
arg.hInstApp = None
ok = shell_execute_ex(arg)
if not ok:
raise ctypes.WinError()
try:
wait_for_single_object(arg.hProcess, -1)
finally:
close_handle(arg.hProcess)