[Python] 纯文本查看 复制代码
import os
import sys
import atexit
import signal
import subprocess
import threading
import tkinter as tk
from tkinter import ttk, messagebox, filedialog, simpledialog
LOCKED_DIRS = []
DEFAULT_LOCK_DIR = "C:\\test"
VIRTUAL_DRIVE = "Z:"
VERIFIED = False
def run_cmd(cmd):
try:
subprocess.run(cmd, shell=True, check=True, capture_output=True, encoding="gbk", timeout=120)
return True
except:
return False
def lock_directory(path):
run_cmd(f'takeown /f "{path}" /r /d y')
run_cmd(f'icacls "{path}" /reset /t')
run_cmd(f'icacls "{path}" /inheritance:r /t')
run_cmd(f'icacls "{path}" /grant "%username%:(OI)(CI)(F)" /t')
run_cmd(f'icacls "{path}" /grant "NT AUTHORITY\\SYSTEM:(OI)(CI)(F)" /t')
run_cmd(f'icacls "{path}" /deny "Everyone:(OI)(CI)(F)" /t')
def unlock_directory(path):
run_cmd(f'icacls "{path}" /reset /t')
run_cmd(f'icacls "{path}" /inheritance:e /t')
def mount_virtual_drive(real_path, drive_letter):
run_cmd(f'subst {drive_letter} /d')
run_cmd(f'subst {drive_letter} "{real_path}"')
import time
time.sleep(0.5)
try:
os.startfile(drive_letter)
except:
pass
def unmount_drive(drive_letter):
run_cmd(f'subst {drive_letter} /d')
def re_lock_all():
for path in LOCKED_DIRS:
if os.path.isdir(path):
try:
lock_directory(path)
except:
pass
LOCKED_DIRS.clear()
def cleanup():
unmount_drive(VIRTUAL_DRIVE)
re_lock_all()
atexit.register(cleanup)
def signal_handler(sig, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
def get_current_password():
from datetime import datetime
return datetime.now().strftime("%H%M")
def verify_password():
for _ in range(3):
pwd = simpledialog.askstring("密码验证", "请输入操作密码:", show="*")
if pwd == get_current_password():
return True
elif pwd is None:
return False
messagebox.showerror("错误", "密码不正确!")
messagebox.showwarning("提示", "验证次数已用完")
return False
def select_dir():
dir_path = filedialog.askdirectory()
if dir_path:
entry_dir.delete(0, tk.END)
entry_dir.insert(0, dir_path)
update_status()
def is_directory_locked(path):
try:
result = subprocess.run(f'icacls "{path}"', shell=True, capture_output=True, encoding="gbk", timeout=10)
output = result.stdout
if "Everyone:(OI)(CI)(N)" in output or "Everyone:(N)" in output or \
"Everyone:(OI)(CI)(DENY)" in output or "Everyone:(DENY)" in output:
return True
return False
except:
return False
def set_buttons_state(enabled):
btn_lock.config(state="normal" if enabled else "disabled")
btn_unlock.config(state="normal" if enabled else "disabled")
def update_status():
path = entry_dir.get().strip()
if not path or not os.path.isdir(path):
status_label.config(text="状态:未知", foreground="gray")
warning_label.config(text="")
set_buttons_state(False)
return
try:
if is_directory_locked(path):
status_label.config(text="状态:已锁定", foreground="red")
warning_label.config(text="")
else:
status_label.config(text="状态:已解锁", foreground="green")
warning_label.config(text="⚠️ 解锁后,记得重新加锁!")
except:
status_label.config(text="状态:未知", foreground="gray")
warning_label.config(text="")
set_buttons_state(True)
def do_lock():
path = entry_dir.get().strip()
if not os.path.isdir(path):
messagebox.showwarning("提示", "目录不存在")
return
status_label.config(text="处理中...", foreground="blue")
warning_label.config(text="")
set_buttons_state(False)
def worker():
unmount_drive(VIRTUAL_DRIVE)
lock_directory(path)
if path not in LOCKED_DIRS:
LOCKED_DIRS.append(path)
root.after(0, on_lock_complete)
threading.Thread(target=worker, daemon=True).start()
def on_lock_complete():
update_status()
def do_unlock_and_mount():
path = entry_dir.get().strip()
if not os.path.isdir(path):
messagebox.showwarning("提示", "目录不存在")
return
status_label.config(text="处理中...", foreground="blue")
warning_label.config(text="")
set_buttons_state(False)
def worker():
unlock_directory(path)
mount_virtual_drive(path, VIRTUAL_DRIVE)
if path in LOCKED_DIRS:
LOCKED_DIRS.remove(path)
root.after(0, on_unlock_complete)
threading.Thread(target=worker, daemon=True).start()
def on_unlock_complete():
update_status()
def on_close():
if LOCKED_DIRS:
if messagebox.askyesno("确认退出", f"还有 {len(LOCKED_DIRS)} 个目录已锁定。\n退出后将保持锁定状态。\n\n确定要退出吗?"):
cleanup()
root.quit()
sys.exit(0)
else:
root.quit()
sys.exit(0)
root = tk.Tk()
root.title("目录安全锁")
root.geometry("580x300")
root.resizable(False, False)
root.protocol("WM_DELETE_WINDOW", on_close)
frame = ttk.Frame(root, padding=20)
frame.pack(expand=True, fill=tk.BOTH)
ttk.Label(frame, text="保护目录:").grid(row=0, column=0, sticky="w", pady=8)
entry_dir = ttk.Entry(frame, width=45)
entry_dir.grid(row=0, column=1, padx=5, pady=8)
entry_dir.insert(0, DEFAULT_LOCK_DIR)
ttk.Button(frame, text="选择目录", command=select_dir).grid(row=0, column=2, padx=5, pady=8)
status_label = ttk.Label(frame, text="状态:未知", foreground="gray", font=("Arial", 11, "bold"))
status_label.grid(row=2, column=1, sticky="w", pady=4)
warning_label = ttk.Label(frame, text="", foreground="red", font=("Arial", 12, "bold"), anchor="center")
warning_label.grid(row=3, column=0, columnspan=3, sticky="ew", pady=4)
frame.grid_columnconfigure(1, weight=1)
btn_frame = ttk.Frame(frame)
btn_frame.grid(row=4, column=0, columnspan=3, pady=15)
btn_lock = ttk.Button(btn_frame, text="🔒 一键上锁", command=do_lock, width=20)
btn_lock.pack(side=tk.LEFT, padx=10)
btn_unlock = ttk.Button(btn_frame, text="🔓 解锁 + 挂载虚拟盘", command=do_unlock_and_mount, width=24)
btn_unlock.pack(side=tk.LEFT, padx=10)
ttk.Label(frame, text="说明:", font=("Arial", 9)).grid(row=5, column=0, sticky="nw", pady=5)
ttk.Label(frame, text=" 上锁:仅自己和系统可访问,其他人无法打开", font=("Arial", 9), foreground="gray").grid(row=5, column=1, sticky="w")
ttk.Label(frame, text=" 解锁+挂载:临时解锁并通过虚拟盘访问,需重新上锁", font=("Arial", 9), foreground="gray").grid(row=6, column=1, sticky="w")
update_status()
entry_dir.bind("<KeyRelease>", lambda e: update_status())
if not verify_password():
root.withdraw()
messagebox.showwarning("提示", "验证失败,程序即将退出")
sys.exit(0)
root.deiconify()
root.mainloop()