我几个月来一直在使用我编写的这段代码来检查我打开的一组窗口是否在特定的窗口标题上停留了给定的秒数,如果是,则关闭它们。该代码在我的 VPS 上持续运行。
import time
import datetime
import win32gui
import win32process
max_downtime = 90
pid_downtimes = {}
cur_pids = []
prev_pids = []
def winEnumHandler(hwnd, ctx):
class_name = win32gui.GetClassName(hwnd)
window_text = win32gui.GetWindowText(hwnd)
if class_name != "ConsoleWindowClass":
return
if not window_text.startswith("Plutonium"):
return
if "Server restarter" in window_text:
return
if "Dedicated Server" in window_text:
return
tid, pid = win32process.GetWindowThreadProcessId(hwnd)
if pid not in pid_downtimes:
pid_downtimes[pid] = 0
pid_downtimes[pid] += 1
if pid_downtimes[pid] >= max_downtime:
print("Server restarted at:", datetime.datetime.now())
win32gui.SendMessage(hwnd, 16) # close window
return
cur_pids.append(pid)
while True:
win32gui.EnumWindows(winEnumHandler, None)
old_pids = [pid for pid in prev_pids if pid not in cur_pids]
for pid in old_pids:
if pid in pid_downtimes:
del pid_downtimes[pid]
prev_pids = cur_pids
cur_pids = []
time.sleep(1)
几天前,第一次崩溃了。
Traceback (most recent call last):
line 43, in <module>
win32gui.EnumWindows(winEnumHandler, None)
line 12, in winEnumHandler
class_name = win32gui.GetClassName(hwnd)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
pywintypes.error: (1400, 'GetClassName', 'Invalid window handle.')
有人知道什么会导致它在平稳运行几个月后崩溃吗?它似乎使用来自
winEnumHandler
的无效窗口句柄启动了函数 win32gui.EnumWindows
,我不知道这是可能的。
根据[MS.Learn]:GetClassName函数(winuser.h)(强调是我的):
如果函数失败,返回值为零。要获取扩展错误信息,请调用 GetLastError 函数。
所以这个函数可以在某些窗口上失败(也许有些窗口没有类?)。所以你的代码必须处理这种情况。可能是这样的:
import pywintypes
# ...
def win_enum_handler(hwnd, ctx):
window_text = win32gui.GetWindowText(hwnd)
try:
class_name = win32gui.GetClassName(hwnd)
except pywintypes.error:
class_name = "Could not be determined"
# ...