add windows autostart (#171)

This commit is contained in:
HonoLite 2026-03-19 11:27:59 +03:00 committed by GitHub
parent 5d839c1112
commit 7eeb447a76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 72 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import ctypes
import json
import logging
import os
import winreg
import psutil
import sys
import threading
@ -34,6 +35,7 @@ DEFAULT_CONFIG = {
"host": "127.0.0.1",
"dc_ip": ["2:149.154.167.220", "4:149.154.167.220"],
"verbose": False,
"autostart": False,
}
@ -165,6 +167,61 @@ def setup_logging(verbose: bool = False):
root.addHandler(ch)
def _autostart_reg_name() -> str:
return APP_NAME
def _autostart_command() -> str:
exe = sys.executable
return f'"{exe}"'
def is_autostart_enabled() -> bool:
try:
with winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
0,
winreg.KEY_READ,
) as k:
val, _ = winreg.QueryValueEx(k, _autostart_reg_name())
stored = str(val).strip()
expected = _autostart_command().strip()
return stored == expected
except FileNotFoundError:
return False
except OSError:
return False
def set_autostart_enabled(enabled: bool) -> None:
try:
with winreg.CreateKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
) as k:
if enabled:
winreg.SetValueEx(
k,
_autostart_reg_name(),
0,
winreg.REG_SZ,
_autostart_command(),
)
else:
try:
winreg.DeleteValue(k, _autostart_reg_name())
except FileNotFoundError:
pass
except OSError as exc:
log.error("Failed to update autostart: %s", exc)
_show_error(
"Не удалось изменить автозапуск.\n\n"
"Попробуйте запустить приложение от имени пользователя с правами на реестр.\n\n"
f"Ошибка: {exc}"
)
def _make_icon_image(size: int = 64):
if Image is None:
raise RuntimeError("Pillow is required for tray icon")
@ -327,7 +384,7 @@ def _edit_config_dialog():
TEXT_SECONDARY = "#707579"
FONT_FAMILY = "Segoe UI"
w, h = 420, 480
w, h = 420, 520
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
root.geometry(f"{w}x{h}+{(sw-w)//2}+{(sh-h)//2}")
@ -378,6 +435,15 @@ def _edit_config_dialog():
corner_radius=6, border_width=2,
border_color=FIELD_BORDER).pack(anchor="w", pady=(0, 8))
# Autostart
autostart_var = ctk.BooleanVar(value=cfg.get("autostart", False))
ctk.CTkCheckBox(frame, text="Автозапуск при включении Windows",
variable=autostart_var, font=(FONT_FAMILY, 13),
text_color=TEXT_PRIMARY,
fg_color=TG_BLUE, hover_color=TG_BLUE_HOVER,
corner_radius=6, border_width=2,
border_color=FIELD_BORDER).pack(anchor="w", pady=(0, 8))
# Info label
ctk.CTkLabel(frame, text="Изменения вступят в силу после перезапуска прокси.",
font=(FONT_FAMILY, 11), text_color=TEXT_SECONDARY,
@ -413,11 +479,14 @@ def _edit_config_dialog():
"port": port_val,
"dc_ip": lines,
"verbose": verbose_var.get(),
"autostart": autostart_var.get(),
}
save_config(new_cfg)
_config.update(new_cfg)
log.info("Config saved: %s", new_cfg)
set_autostart_enabled(bool(new_cfg.get("autostart", False)))
_tray_icon.menu = _build_menu()
from tkinter import messagebox
@ -661,6 +730,8 @@ def run_tray():
log.info("Config: %s", _config)
log.info("Log file: %s", LOG_FILE)
set_autostart_enabled(bool(_config.get("autostart", False)))
if pystray is None or Image is None:
log.error("pystray or Pillow not installed; "
"running in console mode")