# 易语言守护程序与被守护程序示例 我将为你提供一个完整的易语言守护程序解决方案,包含被守护程序(`MainProgram.exe`)和守护程序(`Guardian.exe`)。 ## 被守护程序(MainProgram.e) ```e .版本 2 .程序集 主程序集 .程序集变量 守护进程ID, 整数型 .程序集变量 通信管道, 整数型 .子程序 _启动子程序, 整数型 .局部变量 命令行, 文本型 .局部变量 参数数组, 文本型, , "0" .局部变量 参数个数, 整数型 命令行 = 取命令行 () 参数个数 = 分割文本 (命令行, " ", 参数数组) .如果真 (参数个数 > 0 且 参数数组 [1] = "restart") 信息框 ("程序已由守护进程重新启动", 0, , ) .如果真结束 启动守护进程 () 程序主循环 () 返回 (0) .子程序 启动守护进程 .局部变量 守护进程路径, 文本型 .局部变量 启动信息, 启动信息 守护进程路径 = 取运行目录 () + "\Guardian.exe" .如果真 (文件是否存在 (守护进程路径) = 假) 信息框 ("守护程序不存在:" + 守护进程路径, 0, , ) 结束 () .如果真结束 启动信息.命令行 = 守护进程路径 + " " + 到文本 (取进程ID ()) 启动信息.显示方式 = #隐藏窗口 守护进程ID = 运行 (启动信息, 假) .如果真 (守护进程ID = 0) 信息框 ("启动守护进程失败", 0, , ) 结束 () .如果真结束 通信管道 = 打开内存映射文件 ("GuardianPipe", 1024, 假) .如果真 (通信管道 = 0) 信息框 ("创建通信管道失败", 0, , ) 结束 () .如果真结束 写入内存映射文件 (通信管道, "MainProgram:" + 到文本 (取进程ID ())) .子程序 程序主循环 .局部变量 计数器, 整数型 .局部变量 上次检测时间, 整数型 上次检测时间 = 取启动时间 () 计次循环首 (100, 计数器) 延时 (1000) 输出调试文本 ("主程序运行中: " + 到文本 (计数器)) .如果真 (取启动时间 () - 上次检测时间 > 5000) 上次检测时间 = 取启动时间 () 写入内存映射文件 (通信管道, "Heartbeat:" + 到文本 (取进程ID ())) .如果真结束 计次循环尾 () 关闭内存映射文件 (通信管道) 结束 () .子程序 取进程ID, 整数型 返回 (取现行进程ID ()) ``` ## 守护程序(Guardian.e) ```e .版本 2 .程序集 守护程序集 .程序集变量 被守护进程ID, 整数型 .程序集变量 通信管道, 整数型 .程序集变量 主程序路径, 文本型 .程序集变量 最后心跳时间, 整数型 .子程序 _启动子程序, 整数型 .局部变量 命令行, 文本型 .局部变量 参数数组, 文本型, , "0" .局部变量 参数个数, 整数型 命令行 = 取命令行 () 参数个数 = 分割文本 (命令行, " ", 参数数组) .如果真 (参数个数 < 1) 信息框 ("用法: Guardian.exe <被守护进程ID>", 0, , ) 返回 (1) .如果真结束 被守护进程ID = 到整数 (参数数组 [1]) 主程序路径 = 取运行目录 () + "\MainProgram.exe" 通信管道 = 打开内存映射文件 ("GuardianPipe", 1024, 假) .如果真 (通信管道 = 0) 信息框 ("打开通信管道失败", 0, , ) 返回 (1) .如果真结束 最后心跳时间 = 取启动时间 () 守护循环 () 返回 (0) .子程序 守护循环 .局部变量 读取内容, 文本型 .局部变量 分割数组, 文本型, , "0" .局部变量 分割数量, 整数型 输出调试文本 ("守护进程启动,监控进程ID: " + 到文本 (被守护进程ID)) 判断循环首 (真) 延时 (1000) .如果真 (进程是否存在 (被守护进程ID) = 假) 输出调试文本 ("检测到主程序退出,尝试重启...") 重启主程序 () 跳出循环 () .如果真结束 读取内容 = 读内存映射文件 (通信管道) .如果真 (读取内容 ≠ "") 分割数量 = 分割文本 (读取内容, ":", 分割数组) .如果真 (分割数量 ≥ 2) .判断开始 (分割数组 [1] = "Heartbeat") 最后心跳时间 = 取启动时间 () 输出调试文本 ("收到心跳信号") .判断 (分割数组 [1] = "MainProgram") 被守护进程ID = 到整数 (分割数组 [2]) 输出调试文本 ("更新被守护进程ID: " + 到文本 (被守护进程ID)) .默认 .判断结束 .如果真结束 .如果真结束 .如果真 (取启动时间 () - 最后心跳时间 > 10000) 输出调试文本 ("心跳超时,终止并重启主程序") 终止进程 (被守护进程ID) 重启主程序 () 跳出循环 () .如果真结束 判断循环尾 () 关闭内存映射文件 (通信管道) .子程序 重启主程序 .局部变量 启动信息, 启动信息 启动信息.命令行 = 主程序路径 + " restart" 启动信息.显示方式 = #普通激活 运行 (启动信息, 假) .子程序 进程是否存在, 逻辑型 .参数 进程ID, 整数型 .局部变量 进程列表, 进程信息, , "0" .局部变量 i, 整数型 进程列表 = 取系统进程列表 () .计次循环首 (取数组成员数 (进程列表), i) .如果真 (进程列表 [i].进程标识符 = 进程ID) 返回 (真) .如果真结束 .计次循环尾 () 返回 (假) .子程序 终止进程, 逻辑型 .参数 进程ID, 整数型 返回 (终止进程ById (进程ID)) ``` ## 使用说明 1. 将这两个程序分别编译为`MainProgram.exe`和`Guardian.exe` 2. 将两个exe放在同一目录下 3. 运行`MainProgram.exe`,它会自动启动`Guardian.exe` 4. `MainProgram.exe`会每5秒发送一次心跳信号 5. 如果`Guardian.exe`检测不到心跳(10秒)或发现主程序退出,会自动重启主程序 ## 注意事项 1. 通信机制使用了内存映射文件,确保两个程序在同一台机器运行 2. 守护程序会监控主程序的进程ID和心跳信号 3. 主程序被守护程序重启时会收到"restart"参数 4. 实际使用时可能需要调整心跳间隔和超时时间 ## 额外逻辑点 1. 内存映射文件通信需要确保两个程序有足够的权限访问同一内存区域 2. 进程ID在系统重启后会变化,不适合作为长期标识 3. 心跳机制需要考虑网络延迟和系统负载的影响 [2025-04-09 23:21:01 | AI写代码神器 | 1674点数解答]