# -*- coding: utf-8 -*- """修复「点退出退不出」。 真机现象: 点「退出」-> 服务端停了(8765/8766 释放) -> 进程却一直活着 -> 单实例锁 8767 被占死 -> 再双击 EXE 毫无反应 -> 手表连不上 根因: quit_app() 的 finally 里调用了已经改名的 self._hide_bar() (去悬浮条时改成了 _hide_notice,这里漏改) -> AttributeError 在 finally 中抛出 -> 后面的 self.root.destroy() 永远执行不到 -> 异常冒泡回 Tk 回调,mainloop 继续跑,进程不退 修两处: 1. quit_app 的每步清理各自兜异常,任何一步失败都不能挡住关窗 2. run_agent 收尾强制 os._exit(0),保证"点了退出就真退出" """ from __future__ import annotations import sys from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") UI = ROOT / "windows" / "lanremote" / "ui.py" RUNNER = ROOT / "windows" / "run_agent.py" OLD_QUIT = ''' def quit_app(self) -> None: self._closing = True try: if self.server: self.server.stop() finally: self._hide_bar() try: self.root.destroy() except tk.TclError: pass ''' NEW_QUIT = ''' def quit_app(self) -> None: """退出程序。 每一步清理都单独兜住异常 —— 任何一步失败都不能挡住关窗, 否则用户会觉得「按了退出没反应」。 (真机上踩过:_hide_bar 改名后这里抛 AttributeError, destroy 永远执行不到,进程就一直挂着,单实例锁也放不掉。) """ self._closing = True try: if self.server: self.server.stop() except Exception: pass try: self._hide_notice() except Exception: pass try: self.root.quit() except Exception: pass try: self.root.destroy() except Exception: pass ''' OLD_RUN = ''' try: ui.run() finally: lock.release() return 0 ''' NEW_RUN = ''' try: ui.run() finally: lock.release() # 兜底:确保进程真的退出。 # 窗口关了但进程还在的话,单实例锁会被占死, # 用户再双击 EXE 就毫无反应了。 os._exit(0) ''' OLD_IMPORT = '''import argparse import sys ''' NEW_IMPORT = '''import argparse import os import sys ''' def main() -> int: ok = True text = UI.read_text(encoding="utf-8") if OLD_QUIT not in text: print(" [失败] ui.py quit_app 锚点未匹配") ok = False else: text = text.replace(OLD_QUIT, NEW_QUIT, 1) UI.write_text(text, encoding="utf-8") print(" ui.py: quit_app 已改为逐步兜异常 + 调用 _hide_notice") text = RUNNER.read_text(encoding="utf-8") for old, new, tag in ((OLD_IMPORT, NEW_IMPORT, "import os"), (OLD_RUN, NEW_RUN, "强制退出")): if old not in text: print(f" [失败] run_agent.py {tag} 锚点未匹配") ok = False else: text = text.replace(old, new, 1) if ok: RUNNER.write_text(text, encoding="utf-8") print(" run_agent.py: 已加 os._exit(0) 兜底") print("\n语法检查:") import ast for name, path in (("ui.py", UI), ("run_agent.py", RUNNER)): try: ast.parse(path.read_text(encoding="utf-8")) print(f" {name}: OK") except SyntaxError as exc: print(f" {name}: 语法错误 {exc}") ok = False # 确认没有残留的旧方法名 body = UI.read_text(encoding="utf-8") if "_hide_bar" in body: print(" [失败] ui.py 里仍有 _hide_bar 残留") ok = False else: print(" 残留检查: 没有 _hide_bar") return 0 if ok else 1 if __name__ == "__main__": sys.exit(main())