Is there a reason it’s built as a console application? If it never uses the console as an interactive command-line or text UI, then your script could allocate a console that either has no window or a hidden window, which should be inherited if webdriver.Firefox
spawns the process normally.
It’s simple to allocate a console (or a tab in Windows Terminal, if it’s set as the default terminal) via AllocConsole()
, or attach to an existing console via AttachConsole()
. One also has to set a console control handler via SetConsoleCtrlHandler()
, because a new console connection resets the registered handlers to the default handler that calls ExitProcess()
.
Allocating a console without a window, or without briefly flashing a window, is a bit more complicated. The API doesn’t provide a way to control AllocConsole()
. In the future, Python may provide convenient support for pseudoconsoles (i.e. headless console sessions, introduced in Windows 10). For now this requires spawning a process that allocates the console as desired, with no window or an invisible window, and then attaches to the console of the child.
Example:
import ctypes
import subprocess
import threading
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
ctrl_cancel_event = threading.Event()
ctrl_break_event = threading.Event()
ctrl_close_event = threading.Event()
exit_event = threading.Event()
@ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong)
def ctrl_handler(event_type):
if event_type == 0:
# CTRL_C_EVENT
ctrl_cancel_event.set()
elif event_type == 1:
# CTRL_BREAK_EVENT
ctrl_break_event.set()
else:
# CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, CTRL_SHUTDOWN_EVENT
ctrl_close_event.set()
# Give cleanup handlers time to exit.
exit_event.wait()
return True
def allocate_console(create_window=True):
if create_window:
if not kernel32.AllocConsole():
raise ctypes.WinError(ctypes.get_last_error())
if not kernel32.SetConsoleCtrlHandler(ctrl_handler, True):
raise ctypes.WinError(ctypes.get_last_error())
return
with subprocess.Popen(
'echo ready & set /p=',
shell=True, creationflags=subprocess.CREATE_NO_WINDOW,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
bufsize=0) as p_shell:
try:
p_shell.stdout.read(1)
if not kernel32.AttachConsole(p_shell.pid):
raise ctypes.WinError(ctypes.get_last_error())
if not kernel32.SetConsoleCtrlHandler(ctrl_handler, True):
raise ctypes.WinError(ctypes.get_last_error())
finally:
p_shell.terminate()