[BlueLeaf1336]> PROBLEMS> 探求其之壱>
| history | TOP |
2006/02/04:作成
| overview | TOP |
えらく間が開いてしまいましたが、続きます。まず、タスクマネージャのプロセスタブで一覧されているようなプロセスの列挙をやります。実際にははるか前にパクリ終わってます。ただ、なんとなくですが、プロセスの列挙とそのプロセスに対する処理(メモリの使用量と取ったりすること)を分離しました。
つまり、プロセスの列挙だけを行う関数に、プロセスを見つけた時に呼び出してほしい関数を渡しておいて、プロセス発見時に随時呼び出してもらうようにしました。
| プロセス列挙関数 | TOP |
まずは、プロセスの列挙だけを行う関数です。前述したとおり、引数にプロセス発見時に呼び出したい関数を渡すようになっています。
uses
TLHELP32, PSAPI;
type
// プロセスが見つかったときに呼び出してほしい関数型定義
TCancel = Boolean;
TProcessFound = function(const ProcessEntry: TProcessEntry32;
const Err: Boolean; const ErrText: string): TCancel of object;
//-----------------------------------------------------------------------------
// プロセス一覧を取得
// http://nienie.com/~masapico/api_sample_ps05_c.html
// http://nienie.com/~masapico/api_EnumProcesses.html
// http://support.microsoft.com/default.aspx?scid=kb;ja;JP175030
// http://www.borland.co.jp/qanda/delphi/d0003287.html
// http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=13
procedure SnapShotProcess(CallBack: TProcessFound);
var
SnapShot: THandle;
PE32: TProcessEntry32;
begin
// 構造体の初期化
FillChar(PE32, SizeOf(PE32), 0);
PE32.dwSize := SizeOf(PE32);
try
// システム中の情報のスナップショットをとる
SnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
// 成功した場合
if (SnapShot <> INVALID_HANDLE_VALUE) then
begin
try
// 最初のプロセスの検索
if Process32First(SnapShot, PE32) then
begin
// 通知
repeat
if CallBack(PE32, False, '') then break;
// 次のプロセスの検索
until not Process32Next(SnapShot, PE32);
end
// 検索失敗
else CallBack(PE32, False, '');
finally
CloseHandle(SnapShot);
end;
end
// 失敗した場合
else
begin
CallBack(PE32, True, SysErrorMessage(GetLastError()));
end;
except
on E: Exception do CallBack(PE32, True, E.Message);
end;
end;
| プロセスIDからプロセスハンドルを取得する関数 | TOP |
それから、プロセスIDからプロセスハンドルを取得する関数を作っておきます。プロセスを列挙する関数で直接取得できるのは、TProcessEntry32 構造体に含まれているプロセスIDなんですが、実際にプロセスの情報を取得しようとすると必要になってくるのは、プロセスのハンドルだからです。
あー、その前に、内容を理解しているわけではありません。多分どっかからパクってきてます。参考にしたURLをコメントに書いてないので、ひょっとしたら、PlatformSDKから自分で探したのかも知れません。忘れました。
//-----------------------------------------------------------------------------
// プロセスハンドルの取得
function GetProcessHandle(const ProcessID: Cardinal;
var Handle: THandle; var Err: string): Boolean;
begin
Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessID);
Result := (Handle <> 0);
if not Result then Err := SysErrorMessage(GetLastError());
end;
| バイト数を文字列表示する関数 | TOP |
それから、しょうもないことですが、得られた情報がバイト単位だった場合に、文字列に変換する関数も作っておきます。1024バイト未満であればそのまま、それ以上であればキロバイト単位で表示、1024キロバイト以上ならさらにメガバイト単位で表示する、それだけのものです。
//-----------------------------------------------------------------------------
// バイト数を文字列表示
function B2S(const ByteSize: Int64): string;
var
Check: double;
begin
Check := ByteSize;
if (Check < 1024) then
begin
Result := FormatFloat('#,##0.00 B', Check);
end
else
begin
Check := Check / 1024;
if (Check < 1024) then
begin
Result := FormatFloat('#,##0.00 KB', Check);
end
else
begin
Check := Check / 1024;
Result := FormatFloat('#,##0.00 MB', Check);
end;
//Result := FormatFloat('#,##0.00 KB', Check);
end;
end;
| 今のところかけている取得処理 | TOP |
ここまでの関数を使って、前回放置した時点でかけていたプロセス情報の取得処理です。TProcessMemoryCounters という構造体を仲介に、GetProcessMemoryInfo というAPIを使っていくつかのメモリに関する情報を取得するところまでです。
実際には、グリッドに表示しているのですが、そのあたりの処理は除去しました。おかげで、何の意味もない単なる関数呼び出しの羅列になりましたが、そのあたりはあれで。
//-----------------------------------------------------------------------------
// 見つかったプロセスから情報を取得
// http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpperfmo/html/_win32_GetProcessMemoryInfo.asp
// http://www.ccn.aitai.ne.jp/~ccc/C++/Psapi.txt
// http://nienie.com/~masapico/api_EmptyWorkingSet.html
function TForm1.ProcessFound(const ProcessEntry: TProcessEntry32;
const Err: Boolean; const ErrText: string): TCancel;
function GetValue(const Valid: Boolean; const Value: string): string;
begin
if Valid then Result := Value else Result := '#VAL';
end;
var
hProcess: THandle;
Err2: string;
pmc: TProcessMemoryCounters;
GetProcessMemoryInfoSucceeded: Boolean;
begin
// エラーの場合は無視
if not Err then
begin
// プロセスのメモリ情報を取得
FillChar(pmc, SizeOf(pmc), 0);
GetProcessMemoryInfoSucceeded := False;
// プロセスハンドル取得
if GetProcessHandle(ProcessEntry.th32ProcessID, hProcess, Err2) then
begin
pmc.cb := SizeOf(pmc);
GetProcessMemoryInfo(hProcess, @pmc, SizeOf(pmc));
GetProcessMemoryInfoSucceeded := True;
end;
// イメージ名
//ProcessEntry.szExeFile;
// PID
IntToStr(ProcessEntry.th32ProcessID);
// メモリ使用量
GetValue(GetProcessMemoryInfoSucceeded, B2S(pmc.WorkingSetSize));
// 最大メモリ使用量
GetValue(GetProcessMemoryInfoSucceeded, B2S(pmc.PeakWorkingSetSize));
// ページフォルト
GetValue(GetProcessMemoryInfoSucceeded, B2S(pmc.PageFaultCount));
// 仮想メモリサイズ
GetValue(GetProcessMemoryInfoSucceeded, B2S(pmc.PagefileUsage));
// ページプール
GetValue(GetProcessMemoryInfoSucceeded, B2S(pmc.QuotaPagedPoolUsage));
// 非ページプール
GetValue(GetProcessMemoryInfoSucceeded, B2S(pmc.QuotaNonPagedPoolUsage));
end;
// 全プロセスを列挙する(列挙をキャンセルせずに続ける)
Result := False;
end;
| 進捗状況 | TOP |
今のところ、チェックの入っているデータまで取れてます。ただし、権限が足りないのか一部のプロセスの情報は取り出せないようです。でもまぁ後回し。
| EOF | TOP |