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

[电子教室] 极域电子教室 每1分钟检测学生端程序运行状态,崩溃时自动重启分 三部分

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


2026-03-04_153824.jpg



极域电子教室 每1分钟检测学生端程序运行状态,崩溃时自动重启
分三部分

1、操作说明
2、源代码
3、编译程序下载


操作说明:

1. 确保已安装Python环境并配置好脚本运行环境。将本脚本保存为Python文件(如monitor.py),放置在任意目录。

2. 首次运行:
   - 以管理员身份运行脚本。系统会弹出对话框询问是否禁用任务管理器及Win键组合。
   - 选择"是"将限制用户通过Ctrl+Shift+Esc和任务管理器终止进程;选择"否"则保持原系统功能。

3. 进程监控功能:
   - 脚本会自动监控StudentMain.exe进程(默认路径:C:\Program Files (x86)\Mythware\极域课堂管理系统软件v6.0 2021豪华版\StudentMain.exe)
   - 每60秒检测一次进程状态,若检测到进程异常退出,将自动尝试重启
   - 重启间隔设有60秒冷却期,避免高频异常重启

4. 日志记录:
   - 所有操作记录保存在StudentMain.exe同级目录下的studentmain_monitor.log
   - 包含进程状态、启动结果、异常信息等监控日志

5. 自动化设置:
   - 脚本会自动添加到系统启动项,系统启动时自动运行
   - 监控服务运行时会在后台持续守护进程

6. 特殊功能配置:
   - 若选择禁用任务管理器,系统注册表将被修改(路径:Software\Microsoft\Windows\CurrentVersion\Policies\System)
   - 此修改可通过组策略编辑器或手动修改注册表恢复

7. 路径修改(可选):
   - 若极域学生端安装路径非默认,可通过设置环境变量STUDENTMAIN_PATH指向实际路径
   - 或直接修改代码中PROCESS_PATH常量值后重新运行

8. 注意事项:
   - 所有关键操作(注册表修改/进程控制)需要管理员权限
   - 日志和配置文件与StudentMain.exe位于同一目录
   - 若遇到权限问题,请检查运行环境是否以管理员身份启动

9. 故障排查:
   - 检查studentmain_monitor.pid文件是否存在(位于StudentMain.exe目录)
   - 查看日志文件获取详细错误信息
   - 确保目标进程路径有效且具有可执行权限

该脚本适用于极域电子教室v6.0及以上版本,建议在教学终端部署前先进行测试环境验证。


源代码

import time
import psutil
import subprocess
from datetime import datetime
import os
import sys
import atexit
import ctypes
import winreg as wr
# 配置参数
PROCESS_NAME = "StudentMain.exe"
PROCESS_PATH = os.getenv("STUDENTMAIN_PATH", r"C:\Program Files (x86)\Mythware\极域课堂管理系统软件v6.0 2021豪华版\StudentMain.exe")
# 将日志、PID文件和标志文件都放在StudentMain.exe所在目录
BASE_DIR = os.path.dirname(PROCESS_PATH)
LOG_FILE = os.getenv("LOG_FILE", os.path.join(BASE_DIR, "studentmain_monitor.log"))
PID_FILE = os.getenv("PID_FILE", os.path.join(BASE_DIR, "studentmain_monitor.pid"))
DIALOG_FLAG_FILE = os.getenv("DIALOG_FLAG_FILE", os.path.join(BASE_DIR, "dialog_shown.flag"))
CHECK_INTERVAL = 60
RESTART_COOLDOWN = 60
def log_message(message):
    try:
        # 确保目录存在
        log_dir = os.path.dirname(LOG_FILE)
        if not os.path.exists(log_dir):
            os.makedirs(log_dir, exist_ok=True)
        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'].lower() == PROCESS_NAME.lower():
                if proc_info['exe'] == PROCESS_PATH:
                    return True
        except:
            pass
    return False
def start_process():
    if not os.path.exists(PROCESS_PATH):
        log_message(f"错误:程序路径不存在 - {PROCESS_PATH}")
        return False
    try:
        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 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:
                os.remove(PID_FILE)
    except:
        pass
    try:
        # 确保目录存在
        pid_dir = os.path.dirname(PID_FILE)
        if not os.path.exists(pid_dir):
            os.makedirs(pid_dir, exist_ok=True)
        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:
        os.remove(PID_FILE)
    except:
        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, "StudentMainMonitor", 0, wr.REG_SZ, f'"{exe_path}"')
        log_message("✓ 已添加到开机自启动")
    except Exception as e:
        log_message(f"添加自启动失败: {str(e)}")
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 show_dialog():
    result = ctypes.windll.user32.MessageBoxW(
        None,
        "是否禁用WIN键组合与任务管理器?\n\n选择「是」将限制用户操作\n选择「否」保持正常使用",
        "StudentMain 监控服务配置",
        4 | 0x40
    )
    return result == 6
def monitor_loop():
    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} 运行正常")
            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 not os.path.exists(DIALOG_FLAG_FILE):
        result = show_dialog()
        if result:
            disable_taskmgr()
        # 创建标志文件,表示已经显示过对话框
        try:
            # 确保目录存在
            flag_dir = os.path.dirname(DIALOG_FLAG_FILE)
            if not os.path.exists(flag_dir):
                os.makedirs(flag_dir, exist_ok=True)
            with open(DIALOG_FLAG_FILE, 'w') as f:
                f.write('1')
            log_message("✓ 已创建对话框标记文件,后续运行将不再显示")
        except IOError as e:
            log_message(f"创建标志文件失败: {e}")
   
    add_to_startup()
    monitor_loop()
if __name__ == "__main__":
    main()



编译文件下载 studentmain_monitor.rar (4.4 MB, 下载次数: 18)
回复

使用道具 举报

发表于 昨天 22:33 | 显示全部楼层
收藏一下,也许能用得着
回复

使用道具 举报

发表于 昨天 22:51 | 显示全部楼层
这工具挺实用的,支持一下
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-5 06:08 , Processed in 0.055316 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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