Windowsでプロセスの起動・終了を監視する
Windowsでプロセスの起動・終了を監視するプログラムを書いてみました。コマンドライン引数で指定したプログラムが起動・終了すると音が鳴ります。
Haskellで書く利点はまったくありません。まぁFFIの練習みたいなものです。ところでC言語側からHaskell側にリストを返すのってどうやるんでしょう(まだ既存のソースをあんまり調べてません)。それができれば、もうちょっとC言語側でやらせているロジックが少なくなるんだけどなー。
それにしても、Haskellはスリープすら標準なのが無いのかな。うーむ、Haskellでシステムまわりをいじろうとすると結構苦労しますね。
ファイル: proc.c
#include <HsFFI.h> #include <windows.h> #include <psapi.h> HsBool c_exist_proc(char *pname) { DWORD procs[1024]; DWORD procbytes; int i; if (!EnumProcesses(procs, sizeof(procs), &procbytes)) return HS_BOOL_FALSE; for (i = 0; i < procbytes / sizeof(procs[0]); i++) { TCHAR name[MAX_PATH] = ""; HANDLE hproc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, procs[i]); if (hproc) { HMODULE hmod; DWORD modbytes; if (EnumProcessModules(hproc, &hmod, sizeof(hmod), &modbytes)) GetModuleBaseName(hproc, hmod, name, sizeof(name) / sizeof(name[0])); } CloseHandle(hproc); if (strcmp(pname, name) == 0) return HS_BOOL_TRUE; } return HS_BOOL_FALSE; }
ファイル: pwatch.hs
module Main (main) where import Control.Monad (when) import Data.Word (Word32) import Foreign.C (CString, withCString) import System (getArgs) foreign import stdcall unsafe "Sleep" cSleep :: Word32 -> IO () foreign import stdcall unsafe "MessageBeep" cMesssageBeep :: Word32 -> IO () cMB_ICONASTERISK = 64 cMB_ICONEXCLAMATION = 0x30 cMB_ICONHAND = 16 cMB_ICONQUESTION = 32 cMB_OK = 0 foreign import ccall unsafe "c_exist_proc" cExistProcess :: CString -> IO Bool existProcess :: String -> IO Bool existProcess name = withCString name $ \ cstr -> cExistProcess cstr main :: IO () main = do args <- getArgs if (null args) then putStrLn "usage: pwatch [proc name]" else loop (head args) False loop name prev = do now <- existProcess name when (now /= prev) $ cMesssageBeep cMB_ICONASTERISK cSleep 2000 loop name now -- Local Variables: -- compile-command: "ghc -W -fno-warn-unused-binds -fno-warn-unused-matches -ffi -o pwatch proc.c pwatch.hs -lpsapi -luser32 -lkernel32" -- End:
ちなみにこのプログラムは、ScanSnapで書籍をPDFに変換しているときに、変換の終了を通知するために作りました。音が鳴らないといつ変換終わったのかわからないので、PCの前から離れられないんですよね… ScanSnapの場合、PDFで文字認識しているときにはSSPprCap.exeというプロセスが起動しているので、こんな感じで監視してやります。
$ pwatch SSPprCap.exe