windows mutex-lock
This commit is contained in:
parent
25ae4b0a24
commit
4cbb9e555c
4 changed files with 46 additions and 6 deletions
2
linux.py
2
linux.py
|
|
@ -273,7 +273,7 @@ def run_tray() -> None:
|
|||
|
||||
|
||||
def main() -> None:
|
||||
if not acquire_lock("linux.py"):
|
||||
if not acquire_lock():
|
||||
_show_info("Приложение уже запущено.", os.path.basename(sys.argv[0]))
|
||||
return
|
||||
try:
|
||||
|
|
|
|||
2
macos.py
2
macos.py
|
|
@ -610,7 +610,7 @@ def run_menubar() -> None:
|
|||
|
||||
|
||||
def main() -> None:
|
||||
if not acquire_lock("macos.py"):
|
||||
if not acquire_lock():
|
||||
_show_info("Приложение уже запущено.")
|
||||
return
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ def ensure_dirs() -> None:
|
|||
_lock_file_path: Optional[Path] = None
|
||||
|
||||
|
||||
def _same_process(meta: dict, proc: psutil.Process, script_hint: str) -> bool:
|
||||
def _same_process(meta: dict, proc: psutil.Process) -> bool:
|
||||
try:
|
||||
lock_ct = float(meta.get("create_time", 0.0))
|
||||
if lock_ct > 0 and abs(lock_ct - proc.create_time()) > 1.0:
|
||||
|
|
@ -63,7 +63,7 @@ def _same_process(meta: dict, proc: psutil.Process, script_hint: str) -> bool:
|
|||
return False
|
||||
|
||||
|
||||
def acquire_lock(script_hint: str = "") -> bool:
|
||||
def acquire_lock() -> bool:
|
||||
global _lock_file_path
|
||||
ensure_dirs()
|
||||
for f in list(APP_DIR.glob("*.lock")):
|
||||
|
|
@ -84,7 +84,7 @@ def acquire_lock(script_hint: str = "") -> bool:
|
|||
pass
|
||||
is_running = False
|
||||
try:
|
||||
is_running = _same_process(meta, psutil.Process(pid), script_hint)
|
||||
is_running = _same_process(meta, psutil.Process(pid))
|
||||
except Exception:
|
||||
pass
|
||||
if is_running:
|
||||
|
|
|
|||
42
windows.py
42
windows.py
|
|
@ -56,6 +56,39 @@ from ui.ctk_theme import (
|
|||
_tray_icon: Optional[object] = None
|
||||
_config: dict = {}
|
||||
_exiting = False
|
||||
_win_mutex_handle = None
|
||||
|
||||
_ERROR_ALREADY_EXISTS = 183
|
||||
|
||||
|
||||
def _acquire_win_mutex() -> bool | None:
|
||||
global _win_mutex_handle
|
||||
try:
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32.CreateMutexW.restype = ctypes.c_void_p
|
||||
kernel32.CreateMutexW.argtypes = [ctypes.c_void_p, ctypes.c_bool, ctypes.c_wchar_p]
|
||||
handle = kernel32.CreateMutexW(None, True, "Local\\TgWsProxy_SingleInstance")
|
||||
if kernel32.GetLastError() == _ERROR_ALREADY_EXISTS:
|
||||
kernel32.CloseHandle(ctypes.c_void_p(handle))
|
||||
return False
|
||||
if not handle:
|
||||
return None
|
||||
_win_mutex_handle = handle
|
||||
return True
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _release_win_mutex() -> None:
|
||||
global _win_mutex_handle
|
||||
if _win_mutex_handle:
|
||||
try:
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32.ReleaseMutex(ctypes.c_void_p(_win_mutex_handle))
|
||||
kernel32.CloseHandle(ctypes.c_void_p(_win_mutex_handle))
|
||||
except Exception:
|
||||
pass
|
||||
_win_mutex_handle = None
|
||||
|
||||
ICON_PATH = str(Path(__file__).parent / "icon.ico")
|
||||
|
||||
|
|
@ -350,13 +383,20 @@ def run_tray() -> None:
|
|||
|
||||
|
||||
def main() -> None:
|
||||
if not acquire_lock("windows.py"):
|
||||
if mutex_result := _acquire_win_mutex() is False:
|
||||
_show_info("Приложение уже запущено.", os.path.basename(sys.argv[0]))
|
||||
return
|
||||
if mutex_result is None:
|
||||
log.warning("Named mutex unavailable, falling back to lock file")
|
||||
if not acquire_lock():
|
||||
_show_info("Приложение уже запущено.", os.path.basename(sys.argv[0]))
|
||||
return
|
||||
|
||||
try:
|
||||
run_tray()
|
||||
finally:
|
||||
release_lock()
|
||||
_release_win_mutex()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue