找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 36|回复: 1

[电子教室] 凌波多媒体网络教室7.91 每1分钟检测NCStu.exe运行状态,崩溃时自动重启

[复制链接]
发表于 4 小时前 | 显示全部楼层 |阅读模式
本帖最后由 515151 于 2026-3-3 16:45 编辑


2026-03-03_164453.jpg
操作说明:

一、环境准备
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)



回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层
大佬又出手了,膜拜
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|腾飞在线 ( 冀ICP备05002530号 )

GMT+8, 2026-3-3 20:53 , Processed in 0.056539 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表