とりあえずできた。
起動したアプリを監視して時間を測定する
GetProcessTimes()で起動時間を取得するのは前に書いたとおり。では終了時間はどうするか・・・。WaitForSingleObject()で終了を待って、終了した後に再度GetProcessTimes()でExitTimeを取得する。
/* wait for exit and log */ WaitForSingleObject(pi.hProcess, INFINITE); OutLogFile_end(GetProcessExitTime(pi.hProcess)); FILETIME GetProcessExitTime(HANDLE hProcess){ return GetProcessTime1(hProcess, 1); } FILETIME GetProcessTime1(HANDLE hProcess, int index){ FILETIME ftime[4]; /* CreationTime, ExitTime, KernelTime, UserTime */ FILETIME ltime; GetProcessTimes(hProcess, &ftime[0], &ftime[1], &ftime[2], &ftime[3]); FileTimeToLocalFileTime(&ftime[index], <ime); return ltime; }
とりあえずこれでOK。問題なのは、シャットダウンなどで強制終了された場合、プロセスの終了をwaitする前にアプリ自体が終了してしまう可能性があるので、それをどうするか。waitするとウインドウメッセージをハンドルできないし、その逆もしかり。とりあえず、メインスレッドでアプリの終了をwaitしつつ、別スレッドでメッセージを補足することにしました。
HANDLE hThread; DWORD tid; /* receive wmsg in another thread*/ hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ProcWMsg, NULL, 0, &tid); void ProcWMsg(void){ HWND hwnd; MSG msg; /* open hidden window */ if((hwnd=CreateMinimalWindow()) == NULL) exit(-1); ShowWindow(hwnd, SW_HIDE); /* receive message */ while(GetMessage(&msg, NULL, 0, 0)){ TranslateMessage(&msg); DispatchMessage(&msg); } }
監視対象アプリの終了とメッセージの補足が同時に起こったらログが2重にかかれないか?とも思ったのですが、特に大きな実害はないので放っておくことに。書かれないことが問題なので、どうせ同時に起こるようなときは同じ時間が2回書かれるだけだろうし。うまく排他制御とかすればいいんだろうけど、めんどくさい。数回テストした範囲では2重になるようなことは起こらなかったので、rareなtiming issueなのでしょう。
はてなで小さいファイルとか添付できるようにできればいいんだけどなあ。150行ほどの小さなプログラムでも、blogに張るには長いし・・・。簡易アップローダーみたいなものがあればいいのかな。
ふむ
とりあえず試してみたが、おおむね良好。ツールを意識しないで記録をとる、という最大の目的は果たせそう。起動、終了ごとにログが取れるのでプレイ履歴も分かるという優れものだ。