前言
我们如何通过Electron来检测一些应用程序的状态呢,如:未响应;
内容
获取指定应用程序PID
通过exec
执行cmd命令查询指定应用的PID,并通过electron-store
存储获取到的PID,可参考NodeJs——如何获取Windows电脑指定应用进程信息;
/** * 获取指定应用程序的PID | 只考虑win和linux * @param exeName */ export function cmdFindPidList (exeName, callbackFun) { const cmd = process.platform === 'win32' ? `tasklist -V|findstr "${exeName}" ` : `ps aux | grep ${exeName}`; let pids = []; exec(cmd, (err, stdout, stderr) => { if (err) { callbackFun(pids); return } stdout.split('\n').filter(item => { const p = item.trim().split(/\s+/) // p[0] 应用程序名称 p[1] 应用程序PID if (p[0] && p[1]) { pids.push(p[1]); } }) callbackFun(pids); }) } // 调用 cmdFindPidList('App.exe', (pids) => { // 封装的`electron-store`存储 setStore('AppPids', pids) })
调用user32.dll方法
const User32 = ffi.Library('user32.dll', { EnumWindows: ['bool', ['pointer', 'long']], GetWindowThreadProcessId: ['int', ['long', 'pointer']], IsHungAppWindow: ['bool', ['long']] }) const EnumWindowsProc = ffi.Callback('bool', ['long', 'int32'], function (hwnd, lParam) { let pids = getStore('AppPids') let pidBuff = Buffer.alloc(255) let threadId = User32.GetWindowThreadProcessId(hwnd, pidBuff) let pid = String(pidBuff.readInt32LE(0)) if (pids.includes(pid) && User32.IsHungAppWindow(hwnd)) { // TODO 检测到程序窗口未响应处理方法 } return true }) // 调用 User32.EnumWindows(EnumWindowsProc, 0)
tasklist(推荐)
通过webworker新起一个线程进行检测
import { exec } from 'child_process' onmessage = function (e) { console.info(`worker: ${e.data}`) setInterval(() => { try { exec("tasklist /V /FI \"STATUS ne RUNNING\" | findstr \"xxxx.exe\"", (err, stdout, stderr) => { if (!err) { stdout.split('\n').filter(item => { const p = item.trim().split(/\s+/) // p[0] 应用程序名称 p[1] 应用程序PID 断开连接的时候p[2]会话名会没有一定要注意 if (p[0] ==='xxxx.exe' && p[1]) { try { exec(`taskkill /F /PID ${p[1]} /T`, (error, stdout, stderr) => { if (!error) console.info(`worker: 清除无响应xxxx.exe成功 ===> p[0](应用名称) => ${p[0]}, p[1](应用程序PID) => ${p[1]}`) }) } catch (e) { console.error(`worker: 清除无响应xxxx.exe失败 ===> ${e}`) } } }) } }) } catch (e) { console.error(`worker:关闭无响应xxxx.exe,${e}`) } }, 10000) }
BAT脚本
@echo off :start :: 检测状态为未相应的应用进程 | 所有不理解的命令均可通过帮助进行查看,示例如下 :: for /? for /f "skip=3 tokens=2 " %%i in ('tasklist /V /FI "STATUS ne RUNNING" /FI "imageNAME eq xxx.exe"') do ( ::日志输出文件主要看bat启动位置 echo "%Date% %time% 记录无响应的应用进程PID: %%i" >> "exeStatus.txt" for /f "tokens=3* delims=: " %%j in ('find /C "%%i" exeStatus.txt') do ( ::大于3次 if %%j GTR 3 ( echo "%Date% %time% 开始清除出现%%j次无响应的应用进程PID: %%i">> "DelExePid.txt" taskkill /F /PID %%i /T >> "DelExePid.txt" findstr /V %%i "exeStatus.txt" > "exeStatus.tmp" move /Y exeStatus.tmp exeStatus.txt ) ) ) ::10s检测一次 choice /t 10 /d y /n > null goto start
学无止境,谦卑而行.