add windows autostart (#171)
This commit is contained in:
parent
5d839c1112
commit
7eeb447a76
73
windows.py
73
windows.py
|
|
@ -4,6 +4,7 @@ import ctypes
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import winreg
|
||||||
import psutil
|
import psutil
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
|
@ -34,6 +35,7 @@ DEFAULT_CONFIG = {
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"dc_ip": ["2:149.154.167.220", "4:149.154.167.220"],
|
"dc_ip": ["2:149.154.167.220", "4:149.154.167.220"],
|
||||||
"verbose": False,
|
"verbose": False,
|
||||||
|
"autostart": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -165,6 +167,61 @@ def setup_logging(verbose: bool = False):
|
||||||
root.addHandler(ch)
|
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):
|
def _make_icon_image(size: int = 64):
|
||||||
if Image is None:
|
if Image is None:
|
||||||
raise RuntimeError("Pillow is required for tray icon")
|
raise RuntimeError("Pillow is required for tray icon")
|
||||||
|
|
@ -327,7 +384,7 @@ def _edit_config_dialog():
|
||||||
TEXT_SECONDARY = "#707579"
|
TEXT_SECONDARY = "#707579"
|
||||||
FONT_FAMILY = "Segoe UI"
|
FONT_FAMILY = "Segoe UI"
|
||||||
|
|
||||||
w, h = 420, 480
|
w, h = 420, 520
|
||||||
sw = root.winfo_screenwidth()
|
sw = root.winfo_screenwidth()
|
||||||
sh = root.winfo_screenheight()
|
sh = root.winfo_screenheight()
|
||||||
root.geometry(f"{w}x{h}+{(sw-w)//2}+{(sh-h)//2}")
|
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,
|
corner_radius=6, border_width=2,
|
||||||
border_color=FIELD_BORDER).pack(anchor="w", pady=(0, 8))
|
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
|
# Info label
|
||||||
ctk.CTkLabel(frame, text="Изменения вступят в силу после перезапуска прокси.",
|
ctk.CTkLabel(frame, text="Изменения вступят в силу после перезапуска прокси.",
|
||||||
font=(FONT_FAMILY, 11), text_color=TEXT_SECONDARY,
|
font=(FONT_FAMILY, 11), text_color=TEXT_SECONDARY,
|
||||||
|
|
@ -413,11 +479,14 @@ def _edit_config_dialog():
|
||||||
"port": port_val,
|
"port": port_val,
|
||||||
"dc_ip": lines,
|
"dc_ip": lines,
|
||||||
"verbose": verbose_var.get(),
|
"verbose": verbose_var.get(),
|
||||||
|
"autostart": autostart_var.get(),
|
||||||
}
|
}
|
||||||
save_config(new_cfg)
|
save_config(new_cfg)
|
||||||
_config.update(new_cfg)
|
_config.update(new_cfg)
|
||||||
log.info("Config saved: %s", new_cfg)
|
log.info("Config saved: %s", new_cfg)
|
||||||
|
|
||||||
|
set_autostart_enabled(bool(new_cfg.get("autostart", False)))
|
||||||
|
|
||||||
_tray_icon.menu = _build_menu()
|
_tray_icon.menu = _build_menu()
|
||||||
|
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
|
|
@ -661,6 +730,8 @@ def run_tray():
|
||||||
log.info("Config: %s", _config)
|
log.info("Config: %s", _config)
|
||||||
log.info("Log file: %s", LOG_FILE)
|
log.info("Log file: %s", LOG_FILE)
|
||||||
|
|
||||||
|
set_autostart_enabled(bool(_config.get("autostart", False)))
|
||||||
|
|
||||||
if pystray is None or Image is None:
|
if pystray is None or Image is None:
|
||||||
log.error("pystray or Pillow not installed; "
|
log.error("pystray or Pillow not installed; "
|
||||||
"running in console mode")
|
"running in console mode")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue