Fix exe silent start: show activation window instead of hidden Tk parent.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,18 +4,45 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox, ttk
|
from tkinter import messagebox, ttk
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import hub_client
|
import hub_client
|
||||||
from device_store import is_activated, load_device, machine_fingerprint, save_device
|
from device_store import load_device, machine_fingerprint
|
||||||
|
|
||||||
|
|
||||||
def ensure_activated(root: tk.Tk) -> bool:
|
def _bring_front(win: tk.Misc) -> None:
|
||||||
|
"""确保对话框在 Windows 上可见(避免挂在 withdraw 根窗后不显示)。"""
|
||||||
|
try:
|
||||||
|
win.update_idletasks()
|
||||||
|
win.deiconify()
|
||||||
|
win.lift()
|
||||||
|
win.focus_force()
|
||||||
|
win.attributes("-topmost", True)
|
||||||
|
win.after(200, lambda: win.attributes("-topmost", False))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_activated(parent: Optional[tk.Misc] = None) -> bool:
|
||||||
"""已激活且能 ping 通则通过;否则弹出激活窗。返回是否可继续。"""
|
"""已激活且能 ping 通则通过;否则弹出激活窗。返回是否可继续。"""
|
||||||
device = load_device()
|
device = load_device()
|
||||||
|
owns_root = False
|
||||||
|
root: tk.Misc
|
||||||
|
if parent is not None:
|
||||||
|
root = parent
|
||||||
|
else:
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("黄金市价辅助")
|
||||||
|
root.geometry("360x80")
|
||||||
|
ttk.Label(root, text="正在启动…").pack(expand=True, padx=16, pady=16)
|
||||||
|
root.update()
|
||||||
|
owns_root = True
|
||||||
|
|
||||||
|
try:
|
||||||
if device.get("token") and device.get("server"):
|
if device.get("token") and device.get("server"):
|
||||||
if hub_client.ping():
|
if hub_client.ping():
|
||||||
return True
|
return True
|
||||||
# token 失效时允许重新激活
|
_bring_front(root)
|
||||||
if not messagebox.askyesno(
|
if not messagebox.askyesno(
|
||||||
"激活校验",
|
"激活校验",
|
||||||
"无法连接中控或令牌失效,是否重新激活?\n选「否」将以离线模式继续(不上报复盘)。",
|
"无法连接中控或令牌失效,是否重新激活?\n选「否」将以离线模式继续(不上报复盘)。",
|
||||||
@@ -25,9 +52,9 @@ def ensure_activated(root: tk.Tk) -> bool:
|
|||||||
|
|
||||||
win = tk.Toplevel(root)
|
win = tk.Toplevel(root)
|
||||||
win.title("激活黄金辅助")
|
win.title("激活黄金辅助")
|
||||||
win.geometry("460x280")
|
win.geometry("480x300")
|
||||||
win.transient(root)
|
win.resizable(False, False)
|
||||||
win.grab_set()
|
# 不要 transient 到已隐藏的父窗,否则 Windows 上常不显示
|
||||||
result = {"ok": False}
|
result = {"ok": False}
|
||||||
|
|
||||||
frm = ttk.Frame(win, padding=16)
|
frm = ttk.Frame(win, padding=16)
|
||||||
@@ -60,9 +87,13 @@ def ensure_activated(root: tk.Tk) -> bool:
|
|||||||
status.configure(text="请填写服务器与激活码", foreground="#f6465d")
|
status.configure(text="请填写服务器与激活码", foreground="#f6465d")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
hub_client.activate(server, code, machine_fingerprint(), var_name.get().strip() or "PC")
|
hub_client.activate(
|
||||||
|
server, code, machine_fingerprint(), var_name.get().strip() or "PC"
|
||||||
|
)
|
||||||
result["ok"] = True
|
result["ok"] = True
|
||||||
messagebox.showinfo("激活成功", "已绑定账户与机器,成交将上报复盘中心。", parent=win)
|
messagebox.showinfo(
|
||||||
|
"激活成功", "已绑定账户与机器,成交将上报复盘中心。", parent=win
|
||||||
|
)
|
||||||
win.destroy()
|
win.destroy()
|
||||||
except hub_client.HubError as exc:
|
except hub_client.HubError as exc:
|
||||||
status.configure(text=str(exc), foreground="#f6465d")
|
status.configure(text=str(exc), foreground="#f6465d")
|
||||||
@@ -73,5 +104,13 @@ def ensure_activated(root: tk.Tk) -> bool:
|
|||||||
ttk.Button(btns, text="激活", command=do_ok).pack(side=tk.RIGHT)
|
ttk.Button(btns, text="激活", command=do_ok).pack(side=tk.RIGHT)
|
||||||
|
|
||||||
win.protocol("WM_DELETE_WINDOW", do_skip)
|
win.protocol("WM_DELETE_WINDOW", do_skip)
|
||||||
|
_bring_front(win)
|
||||||
|
win.grab_set()
|
||||||
root.wait_window(win)
|
root.wait_window(win)
|
||||||
return result["ok"]
|
return result["ok"]
|
||||||
|
finally:
|
||||||
|
if owns_root:
|
||||||
|
try:
|
||||||
|
root.destroy()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|||||||
@@ -1472,14 +1472,10 @@ class OrderApp(tk.Tk):
|
|||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
enable_dpi_awareness()
|
enable_dpi_awareness()
|
||||||
# 先建隐藏根窗完成激活,再开主界面
|
# 激活窗自管可见性(勿对隐藏根窗挂 Toplevel,Windows 上会双击无界面)
|
||||||
boot = tk.Tk()
|
|
||||||
boot.withdraw()
|
|
||||||
if ensure_activated is not None:
|
if ensure_activated is not None:
|
||||||
if not ensure_activated(boot):
|
if not ensure_activated():
|
||||||
boot.destroy()
|
|
||||||
return
|
return
|
||||||
boot.destroy()
|
|
||||||
|
|
||||||
app = OrderApp()
|
app = OrderApp()
|
||||||
if is_activated():
|
if is_activated():
|
||||||
@@ -1495,4 +1491,23 @@ def main() -> None:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
main()
|
main()
|
||||||
|
except Exception as exc:
|
||||||
|
try:
|
||||||
|
import traceback
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
log = Path.home() / ".gold_monitor" / "crash.log"
|
||||||
|
log.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
log.write_text(traceback.format_exc(), encoding="utf-8")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
root = tk.Tk()
|
||||||
|
root.withdraw()
|
||||||
|
messagebox.showerror("黄金市价辅助", f"启动失败:{exc}\n详情见 %USERPROFILE%\\.gold_monitor\\crash.log")
|
||||||
|
root.destroy()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
raise
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user