前言
我們如何通過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