|
|
本帖最后由 515151 于 2026-3-3 16:45 编辑
操作说明:
一、环境准备
1. 确保已安装Python环境(建议Python 3.7+)
2. 安装依赖库:
pip install psutil
3. 以管理员身份运行Python脚本(右键->以管理员身份运行)
二、配置参数修改(根据实际情况调整)
1. 打开脚本文件修改以下变量(位于代码顶部):
- PROCESS_PATH:NCStu.exe实际路径(默认C:\Program Files (x86)\lingbo\netclass7\NCStu.exe)
- LOG_FILE:日志文件保存路径(默认ncstu_monitor.log)
- PID_FILE:进程标识文件路径(默认ncstu_monitor.pid)
三、运行程序
1. 双击运行脚本文件或在命令行执行:
python ncstu_monitor.py
2. 初次运行会弹出配置对话框,选择:
- [是]:禁用任务管理器并限制系统热键
- [否]:保持系统正常功能
四、核心功能说明
1. 自动监控:
每1分钟检测NCStu.exe运行状态,崩溃时自动重启
重启间隔至少保持1分钟冷却时间
2. 自启动设置:
首次运行后会自动添加开机启动项
可通过系统设置取消:控制面板 -> 管理工具 -> 启动项
3. 日志记录:
所有操作记录在指定日志文件中
记录内容包含时间戳和详细状态信息
4. 系统保护:
- 禁用任务管理器(需管理员权限)
- 阻止通过Ctrl+Shift+Esc等快捷键打开任务管理器
五、异常处理
1. 进程路径错误:
日志提示"程序路径不存在"时,请检查PROCESS_PATH配置
2. 权限不足问题:
运行时需始终使用管理员权限,否则无法修改注册表设置
3. 强制停止:
删除PID文件(ncstu_monitor.pid)可终止监控服务
六、恢复系统设置
1. 恢复任务管理器:
重新运行程序并选择"否"选项
或手动删除注册表项:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableTaskMgr
2. 移除自启动:
通过系统启动项管理界面取消勾选"NCStuMonitor"条目
注意事项:
1. 修改配置后需重新启动监控程序
2. 日志文件默认保存在脚本所在目录
3. 程序运行期间不可同时存在多个实例
4. 修改注册表操作需谨慎,建议备份注册表数据
import time
import psutil
import subprocess
from datetime import datetime
import os
import sys
import atexit
import ctypes
import winreg as wr
# ==================== 配置参数 ====================
PROCESS_NAME = "NCStu.exe"
PROCESS_PATH = os.getenv("NCSTU_PATH", r"C:\Program Files (x86)\lingbo\netclass7\NCStu.exe")
LOG_FILE = os.getenv("LOG_FILE", "ncstu_monitor.log")
PID_FILE = os.getenv("PID_FILE", "ncstu_monitor.pid")
CHECK_INTERVAL = 60 # 检测间隔:60秒(1分钟)
RESTART_COOLDOWN = 60 # 重启冷却时间:60秒
# ==================== 日志模块 ====================
def log_message(message):
"""记录日志到文件"""
try:
with open(LOG_FILE, 'a', encoding='utf-8') as f:
f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {message}\n")
except Exception as e:
print(f"日志写入失败: {e}")
# ==================== 进程检测模块 ====================
def is_process_running():
"""检查目标进程是否正在运行"""
for proc in psutil.process_iter(['pid', 'name', 'exe']):
try:
proc_info = proc.info
if proc_info['name'] and proc_info['name'].lower() == PROCESS_NAME.lower():
# 如果路径匹配或路径为空(兼容不同情况)
if proc_info['exe'] is None or proc_info['exe'] == PROCESS_PATH:
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False
# ==================== 进程启动模块 ====================
def start_process():
"""启动目标进程"""
try:
# 检查路径是否存在
if not os.path.exists(PROCESS_PATH):
log_message(f"错误:程序路径不存在 - {PROCESS_PATH}")
return False
# 启动进程
subprocess.Popen(
PROCESS_PATH,
creationflags=subprocess.CREATE_NO_WINDOW,
cwd=os.path.dirname(PROCESS_PATH),
shell=False
)
log_message(f"✓ 已成功启动 {PROCESS_NAME}")
return True
except FileNotFoundError:
log_message(f"错误:找不到程序文件 - {PROCESS_PATH}")
return False
except PermissionError:
log_message("错误:权限不足,可能需要管理员权限")
return False
except Exception as e:
log_message(f"启动失败:{str(e)}")
return False
# ==================== 单实例检测模块 ====================
def is_already_running():
"""检查是否已有监控实例在运行"""
try:
if os.path.exists(PID_FILE):
with open(PID_FILE, 'r') as f:
old_pid = f.read().strip()
if old_pid and psutil.pid_exists(int(old_pid)):
log_message("检测到已有监控实例在运行,当前实例退出")
return True
else:
# 清理无效的PID文件
try:
os.remove(PID_FILE)
except OSError:
pass
except (IOError, ValueError, ProcessLookupError):
pass
# 写入当前PID
try:
with open(PID_FILE, 'w') as f:
f.write(str(os.getpid()))
except IOError as e:
log_message(f"警告:无法创建PID文件 - {e}")
return False
# ==================== 清理模块 ====================
def cleanup():
"""清理资源"""
try:
if os.path.exists(PID_FILE):
os.remove(PID_FILE)
except OSError:
pass
log_message("监控服务已停止")
# ==================== 自启动模块 ====================
def add_to_startup():
"""添加到开机自启动"""
key_path = r"Software\Microsoft\Windows\CurrentVersion\Run"
exe_path = os.path.abspath(sys.argv[0])
try:
with wr.OpenKey(wr.HKEY_CURRENT_USER, key_path, 0, wr.KEY_SET_VALUE) as key:
wr.SetValueEx(key, "NCStuMonitor", 0, wr.REG_SZ, f'"{exe_path}"')
log_message("✓ 已添加到开机自启动")
return True
except Exception as e:
log_message(f"添加自启动失败: {str(e)}")
return False
# ==================== 任务管理器控制模块 ====================
def disable_taskmgr():
"""禁用任务管理器"""
key_path = r"Software\Microsoft\Windows\CurrentVersion\Policies\System"
try:
with wr.CreateKey(wr.HKEY_CURRENT_USER, key_path) as key:
wr.SetValueEx(key, "DisableTaskMgr", 0, wr.REG_DWORD, 1)
log_message("已禁用任务管理器")
except Exception as e:
log_message(f"禁用任务管理器失败: {str(e)}")
def enable_taskmgr():
"""启用任务管理器"""
key_path = r"Software\Microsoft\Windows\CurrentVersion\Policies\System"
try:
with wr.OpenKey(wr.HKEY_CURRENT_USER, key_path, 0, wr.KEY_SET_VALUE) as key:
wr.DeleteValue(key, "DisableTaskMgr")
except Exception:
pass
log_message("已恢复任务管理器")
# ==================== 对话框模块 ====================
def show_dialog():
"""显示配置对话框"""
result = ctypes.windll.user32.MessageBoxW(
None,
"是否禁用WIN键组合与任务管理器?\n\n选择「是」将限制用户操作\n选择「否」保持正常使用",
"NCStu 监控服务配置",
4 | 0x40 # MB_YESNO | MB_ICONINFORMATION
)
return result == 6 # IDYES
# ==================== 主监控循环 ====================
def monitor_loop():
"""主监控循环 - 每1分钟检测一次"""
log_message("=" * 50)
log_message(f"监控服务启动 - 目标进程: {PROCESS_NAME}")
log_message(f"检测间隔: {CHECK_INTERVAL}秒")
log_message(f"目标路径: {PROCESS_PATH}")
log_message("=" * 50)
last_restart_time = 0
while True:
try:
if not is_process_running():
current_time = time.time()
# 检查冷却时间,避免频繁重启
if current_time - last_restart_time >= RESTART_COOLDOWN:
log_message(f"检测到 {PROCESS_NAME} 未运行,正在启动...")
if start_process():
last_restart_time = current_time
else:
log_message(f"冷却中,跳过本次启动尝试")
else:
log_message(f"✓ {PROCESS_NAME} 运行正常")
# 等待下次检测(1分钟)
time.sleep(CHECK_INTERVAL)
except KeyboardInterrupt:
log_message("收到停止信号")
break
except Exception as e:
log_message(f"监控异常: {str(e)}")
time.sleep(CHECK_INTERVAL)
# ==================== 主函数 ====================
def main():
"""主函数"""
# 检查单实例
if is_already_running():
sys.exit(0)
# 注册清理函数
atexit.register(cleanup)
# 显示配置对话框
#if show_dialog():
disable_taskmgr()
# 添加自启动
add_to_startup()
# 启动监控循环
monitor_loop()
if __name__ == "__main__":
main()
编译好程序下载
wl2.rar
(5.27 MB, 下载次数: 24)
|
|