Electron——如何檢測應用程序的未響應狀態


前言

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM