-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdrekar_launch_process.py
151 lines (121 loc) · 5.33 KB
/
drekar_launch_process.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import sys
import atexit
import traceback
import threading
def wait_exit():
#Wait for shutdown signal if running in service mode
#print("Press Ctrl-C to quit...")
if sys.platform == "win32":
_win32_wait_exit()
else:
import signal
signal.sigwait([signal.SIGTERM,signal.SIGINT])
def wait_exit_callback(callback):
if sys.platform != "win32":
evt = threading.Event()
def t_func():
try:
#Wait for shutdown signal if running in service mode
#print("Press Ctrl-C to quit...")
if sys.platform == "win32":
hwnd = _win32_create_message_hwnd()
def _stop_loop():
_win32_post_hwnd_close(hwnd)
try:
atexit.register(_stop_loop)
_win32_wait_message_hwnd(hwnd)
finally:
try:
atexit.unregister(_stop_loop)
except Exception: pass
else:
evt.wait()
except Exception:
traceback.print_exc()
callback()
t = threading.Thread(target=t_func)
t.setDaemon(True)
t.start()
# Block signals in main thread
if sys.platform != "win32":
import signal
# Send signals to noop handler in main thread
def noop_handler(signum, frame):
evt.set()
signal.signal(signal.SIGTERM, noop_handler)
signal.signal(signal.SIGINT, noop_handler)
def wait_exit_stop_loop(loop):
wait_exit_callback(lambda: loop.call_soon_threadsafe(loop.stop))
if sys.platform == "win32":
# https://gist.github.com/mouseroot/6128651
import ctypes
import ctypes.wintypes
WNDPROCTYPE = ctypes.WINFUNCTYPE(ctypes.wintypes.LPARAM, ctypes.wintypes.HWND, ctypes.wintypes.UINT,
ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)
CtrlCHandlerRoutine = ctypes.WINFUNCTYPE(ctypes.wintypes.BOOL, ctypes.wintypes.DWORD)
WM_DESTROY = 2
WM_CLOSE = 16
HWND_MESSAGE = ctypes.wintypes.HWND(-3)
CTRL_C_EVENT = 0
CTRL_BREAK_EVENT = 1
CTRL_CLOSE_EVENT = 2
class WNDCLASSEX(ctypes.Structure):
_fields_ = [("cbSize", ctypes.c_uint),
("style", ctypes.c_uint),
("lpfnWndProc", WNDPROCTYPE),
("cbClsExtra", ctypes.c_int),
("cbWndExtra", ctypes.c_int),
("hInstance", ctypes.wintypes.HANDLE),
("hIcon", ctypes.wintypes.HANDLE),
("hCursor", ctypes.wintypes.HANDLE),
("hBrush", ctypes.wintypes.HANDLE),
("lpszMenuName", ctypes.wintypes.LPCWSTR),
("lpszClassName", ctypes.wintypes.LPCWSTR),
("hIconSm", ctypes.wintypes.HANDLE)]
def _PyWndProcedure(hWnd, Msg, wParam, lParam):
if Msg == WM_DESTROY:
ctypes.windll.user32.PostQuitMessage(0)
elif Msg == WM_CLOSE:
ctypes.windll.user32.DestroyWindow(hWnd)
else:
return ctypes.windll.user32.DefWindowProcW(hWnd, Msg, ctypes.wintypes.WPARAM(wParam),
ctypes.wintypes.LPARAM(lParam))
return 0
WndProc = WNDPROCTYPE(_PyWndProcedure)
def _ctrl_c_empty_handler(code):
return True
_ctrl_c_empty_handler_ptr = CtrlCHandlerRoutine(_ctrl_c_empty_handler)
def _win32_wait_exit():
hwnd = _win32_create_message_hwnd()
_win32_wait_message_hwnd(hwnd)
def _win32_create_message_hwnd():
hInst = ctypes.windll.kernel32.GetModuleHandleW(0)
wclassName = 'drekar_message_window'
wname = 'drekar_hidden_window'
wndClass = WNDCLASSEX()
wndClass.cbSize = ctypes.sizeof(WNDCLASSEX)
wndClass.lpfnWndProc = WndProc
wndClass.lpszClassName = wclassName
wndClass.hInstance = hInst
regRes = ctypes.windll.user32.RegisterClassExW(ctypes.byref(wndClass))
assert regRes, "Could not create win32 message wnd class"
hWnd = ctypes.windll.user32.CreateWindowExW( 0, wclassName, wname, 0, 0, 0, 0, 0, HWND_MESSAGE, None, None, None )
assert hWnd, "Could not create win32 message hwnd"
return hWnd
def _win32_wait_message_hwnd(hWnd):
# Install a ctrl-c handler to send WM_QUIT
def ctrl_c_handler(code):
if (code in (CTRL_C_EVENT, CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT)):
_win32_post_hwnd_close(hWnd)
return True
ctrl_c_handler_ptr = CtrlCHandlerRoutine(ctrl_c_handler)
ctypes.windll.kernel32.SetConsoleCtrlHandler(ctrl_c_handler_ptr, 1)
msg = ctypes.wintypes.MSG()
lpmsg = ctypes.pointer(msg)
while ctypes.windll.user32.GetMessageA(lpmsg, 0, 0, 0) != 0:
ctypes.windll.user32.TranslateMessage(lpmsg)
ctypes.windll.user32.DispatchMessageA(lpmsg)
ctypes.windll.kernel32.SetConsoleCtrlHandler(_ctrl_c_empty_handler_ptr, 1)
def _win32_post_hwnd_close(hWnd):
ctypes.windll.user32.PostMessageW(hWnd,WM_CLOSE,0,0)
__all__ = ["wait_exit","wait_exit_callback","wait_exit_stop_loop"]