タスクマネージャのデータを取得したい

解決


歩如  2008-09-03 19:33:52  No: 31770

タスクマネージャで表示されているデータを取得したいのですが、
どのような関数を呼べばよいのでしょうか?

Delphi2007 Vista  です

メモリサイズは
GetProcessMemoryInfo(hProcess, @MemInfo, sizeof(MemInfo));
で取得できたのですが、

ハンドル数を取得する方法がわからないので
教えて欲しいのです。


歩如  2008-09-04 02:48:42  No: 31771

NtQuerySystemInformation

このAPI関数を使うとできそうなことが書かれていましたが
使い方がよくわかりません。
どなたか教えていただけないでしょうか?


igy  2008-09-04 06:41:07  No: 31772

タスクマネージャのCPU使用率を取得するには?
https://www.petitmonte.com/bbs/answers?question_id=5790

などは、どうですか?

あと、Googleなどで検索してみるとか・・・


歩如  2008-09-04 17:23:42  No: 31773

どうやら、
NtQuerySystemInformation は
Windows Vista 上では動作しないみたいです。

Windows Vista 上で可能な方法を教えてください。

やりたいことは、起動しているあるプログラムを指定し、
指定したプログラムのメモリ使用量、ハンドル数を
取得する方法です。
メモリ使用量は取得できましたが、ハンドル数の取得ができません。
よろしくお願いします。


歩如  2008-09-05 05:54:49  No: 31774

できればVistaで動作させたいのですが、
XPのコードもわからないので
XPでの動作させる方法も合わせて教えて
いただけないでしょうか?
よろしくお願いします。


monaa  2008-09-06 03:36:30  No: 31775

ググったらそのものズバリっぽいのがありました。
GetProcessHandleCount
静的ロードで試してみたところそれっぽい値は返ってきました。
function GetProcessHandleCount(hProcess:THandle; pdwHandleCount:PDWORD): BOOL; stdcall; external 'Kernel32.dll' name 'GetProcessHandleCount';


歩如  2008-09-09 20:46:40  No: 31776

ありがとうございます。
ハンドル数は取得できました。

あと、どうしても欲しいのがCPUの使用率ですが。
igy さんのだと全体の使用率がわかるのですが
各プロセスごとのCPU使用率がわかりません。

hProcess:THandle を使って何らかのファンクションを
呼び出すだけで現在の(タスクマネージャーの表示と同期のように)
取得できないのでしょうか?


Mr.XRAY  2008-09-11 02:37:06  No: 31777

横から失礼します.

>呼び出すだけで現在の(タスクマネージャーの表示と同期のように)

タスクマネージャの情報を読み取るということでしょうか.
ですと,タスクマネージャーが起動していないとできませんよね?
もっとも,方法はわかりませんが.

>NtQuerySystemInformation は
>Windows Vista 上では動作しないみたいです。

動作します.
以下のコードは,NtQuerySystemInformationでプロセス名の一覧をListViewに
表示するものです.
このコードで,AInfo.qUserTimeとすれば,そのプロセスのユーザ使用時間が
求まります.またカーネルの使用時間も求まります.

残念ながら,CPUの使用率の詳しい計算方法は知りませんが.
システムで使用した時間に対する,対象プロセスのCPU使用時間の割合では
ないかと思います.
つまり,一定の時間内ののCPUの使用時間を取得する必要があります.
ということは,NtQuerySystemInformationを2回実行することになります.
そこで,前のプロセス,カーネル時間,ユーザ時間を保存しておいて,次
にNtQuerySystemInformationを実行した時の情報から算出することに
なるでしょう.
結構面倒な気がします.

igyさんがレスしているリンクが参考になります.
違いは,NtQuerySystemInformationの引数です.全体かプロセス単位かは.
またこれもigyさんがレスしていますが,ネットで検索すると,そのもの
ではありませんが,参考になるサンプルが結構あります.
あとは,やるだけです.
くどいようですが,CPU使用率の計算方法を知らないとできないですね(笑).
                      
WMIを使用する方法もあるようです.
http://www.online-admin.com/twmiperformancemonitor.html
のTWmiPerformanceMonitor componentがそうです(コンポーネントですね)

では,がんばってください.

------------  サンプルコード  ---------------
使用コントロールはTListViewのみ

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormShow(Sender: TObject);
  private
    ABuffer: array[0..65536] of Byte;
    procedure ListProcessName;
  public
  end;

  //SYSTEM_PROCESS_INFORMATIONレコード型の定義
  //Delphiでは定義がないので定数なども定義する必要あり
  //[MicrosoftのOnlien資料]
  //http://msdn.microsoft.com/en-us/library/ms724509(VS.85).aspx
  //その他,
  //NtQuerySystemInformation
  //NtQuerySystemInformation Delphi
  //でネットを検索すると情報あり
  _SYSTEM_PROCESS_INFORMATION = packed record
    dNext: DWORD;
    dThreadCount: DWORD;
    dReserved01: DWORD;
    dReserved02: DWORD;
    dReserved03: DWORD;
    dReserved04: DWORD;
    dReserved05: DWORD;
    dReserved06: DWORD;
    qCreateTime: LARGE_INTEGER;
    qUserTime: LARGE_INTEGER;
    qKernelTime: LARGE_INTEGER;
    usLength: WORD;
    usMaximumLength: WORD;
    usName: Pointer;
    BasePriority: DWORD;
    dUniqueProcessId: DWORD;
    dInheritedFromUniqueProcessId: DWORD;
    dHandleCount: DWORD;
    dReserved07: DWORD;
    dReserved08: DWORD;
    PeakVirtualSize: DWORD;
    VirtualSize: DWORD;
    PageFaultCount: DWORD;
    PeakWorkingSetSize: DWORD;
    WorkingSetSize: DWORD;
    QuotaPeakPagedPoolUsage: DWORD;
    QuotaPagedPoolUsage: DWORD;
    QuotaPeakNonPagedPoolUsage: DWORD;
    QuotaNonPagedPoolUsage: DWORD;
    PagefileUsage: DWORD;
    PeakPagefileUsage: DWORD;
    dCommitCharge: DWORD;
  end;
  TSYSTEM_PROCESS_INFORMATION = _SYSTEM_PROCESS_INFORMATION;
  PSYSTEM_PROCESS_INFORMATION = ^TSYSTEM_PROCESS_INFORMATION;

  //Dll内の関数の利用方法は他にもあり
  function NtQuerySystemInformation(pSystemInformationClass: Integer;
                                    pSystemInformation: Pointer;
                                    pSystemInformationLength: Integer;
                                    pReturnLength: Pointer): Integer; stdcall;

//このサンプルでは1しか使用しないが定義しておく
const
  SystemBasicInformation = 0;
  SystemPerformanceInformation = 2;
  SystemTimeOfDayInformation = 3;
  SystemProcessInformation = 5;
  SystemProcessorPerformanceInformation = 8;
  SystemInterruptInformation = 23;
  SystemExceptionInformation = 33;
  SystemRegistryQuotaInformation = 37;
  SystemLookasideInformation = 45;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function NtQuerySystemInformation;
  external 'ntdll.dll' name 'NtQuerySystemInformation';

procedure TForm1.FormShow(Sender: TObject);
begin
    ListView1.Columns.Add;
    ListView1.Columns[0].Width := 200;
    ListProcessName;
end;

procedure TForm1.ListProcessName;
var
    Cnt   : Integer;
    AInfo : PSYSTEM_PROCESS_INFORMATION;
    AItem : TListItem;
begin
    //プロセス情報取得
    if (NtQuerySystemInformation(SystemProcessInformation,
                                 @ABuffer,
                                 SizeOf(ABuffer),
                                 nil) = 0) then begin

      //ListViewにプロセス名のみ表示
      //プロセス名以外の情報はAInfoレコード型の各メンバーから取得可能
      Cnt := 0;
      while (True) do begin
        AInfo := @ABuffer[Cnt];
        AItem := ListView1.Items.Add;
        AItem.Caption := PWideChar(AInfo.usName);

        if (AInfo.dNext = 0) then Break;
        Inc(Cnt, AInfo.dNext);
      end;
    end;
end;

end.


Mr.XRAY  2008-09-11 02:38:43  No: 31778

失礼.
動作確認環境は以下の通りです.

Windows XP(SP2) + Delphi7 Pro
Windows Vista + Delphi2007


Mr.XRAY  2008-09-11 07:46:09  No: 31779

サンプルがありましたね.
探せばあるもんです.

Win32プロセス情報をまるごと取得する方法
http://brainwork.seesaa.net/article/5340148.html

>この記事を読んで役に立ったと思うあなた、
>私にビール1本おごってくださいね。(笑い)

ということだそうです.(^_^;)


歩如  2008-09-11 18:31:14  No: 31780

ありがとうございます。
Win32プロセス情報をまるごと取得する方法
http://brainwork.seesaa.net/article/5340148.html

このプログラムを実行すると、
やはりVISTA では動作しませんでした。
リストビューの各プロセスごとの情報が表示されません。
XPでは動作します。

ちなみに以下のようなテストプロを作成しました。
エラーコード(-1073741820[$C0000004])が発生します。

const
  SystemProcessInformation = 5;

procedure TForm1.Button1Click(Sender: TObject);
const
  BUF1SIZE = 65536;
var
  IRet:  Integer;
  FBuf1:  array [0..BUF1SIZE - 1] of Byte;
begin
  IRet := NtQuerySystemInformation(SystemProcessInformation, @FBuf1, BUF1SIZE, nil);
  if IRet = 0
    then ShowMessage('Success')
    else ShowMessage('Eorror=' + IntToStr(IRet));
end;


Mr.XRAY  2008-09-11 22:40:30  No: 31781

当方のVistaではどちらも正常動作しています.
VistaでSP1を導入すると,問題があるという情報がありましたが... 
それとも

http://support.codegear.com/jp/article/37536

参考までに,当方はDelphi2007-R2(UP3相当)です.


monaa  2008-09-11 23:08:43  No: 31782

Vsitaアプリ、管理者権限で動作させてるんですかね?


歩如  2008-09-12 02:08:10  No: 31783

ありがとうございます。

こちらの動作条件は以下のとおりです

OS :  Windows Vista SP1 です。
CodeGearRAD の Delphi2007 を使用しています。
管理者権限で動作させています。


Mr.XRAY  2008-09-12 02:31:49  No: 31784

これ以上は進めないようですね.
Delphiのアップデートをしてもダメなら,CodeGear(エンバカデロ)に問い合わせる
しかないのでは.幸いにも簡単なテストプログラムもあることですし.
報告お待ちしております (^_^;)

それとも私のVistaとDelphi2007-R2が異常?
う〜ん.わかりません.


Mr.XRAY  2008-09-12 04:43:30  No: 31785

>それとも私のVistaとDelphi2007-R2が異常?

というわけで,
もし,もしもです.このスレッドの発言を読んでいて不安になった方,
テストプログラムを用意しました.
よろしかったらテストしてみてください.

http://mrxray.on.coocan.jp/Others/NtdllTest01.htm


TS  2008-09-12 04:56:52  No: 31786

NtQuerySysInfoTest.exeを実行
Button1をクリック
Eorror=-1073741820と出ます。
WindowsXP SP3です。


Mr.XRAY  2008-09-12 05:23:45  No: 31787

>Eorror=-1073741820と出ます。
>WindowsXP SP3です。

え〜!?
私のPCの環境に何かが... 
テストありがとうございます.後で調べてみます.


monaa  2008-09-12 06:18:37  No: 31788

とりあえずテストだけしてみました。
Error=-1073741820
Vista最新
ソースチェックはすぐにはできません。


ofZ  2008-09-12 06:58:30  No: 31789

Windows XP SP2 で成功しました。


結果はSuccess  2008-09-12 08:46:47  No: 31790

WindowsXP SP2でも、
WindowsXP SP3でも、実行結果は成功。


歩如  2008-09-12 17:23:15  No: 31791

Mr.XRAY さん  いろいろお手を煩わせてすみません。
また、テストしていただいたみなさんありがとうございます。
私の環境でも、XP-SP2 では動作しています。
Vista SP1 が動作しないのです。
XP が動作すると思っていたのですが、XP SP3 でも
動作しない環境があるんですね。

ひょっとして、CPUの差があるのでしょうか?
CPUのコードチェックとか?

ちなみに私のマシンの環境は・・・

VISTA-SP1 は E8500 です。
WinXP-SP2 は Pentium4 です。


歩如  2008-09-12 17:44:03  No: 31792

と思って調べてみたのですが

X5335 VISTA  SP--   NG
X5335 VISTA  SP1    OK
E6850 VISTA  SP1    OK
E8500 VISTA  SP1    NG

以上調査までです。
何かわかったらまた教えてください。
現在、原因が不明です。


Mr.XRAY  2008-09-13 03:36:31  No: 31793

いろいろテストありがとうございます.
う〜ん,何がなんだが...
本題と違う方向に流れている気がして,質問された方には申し訳ないです.
ネットで調べてみたのですが,わかりません.

NtQuerySystemInformation "-1073741820"  で検索したら以下のページがありました.
同じ様な現象にあっているようです.解決はしていないのかな?  パニックっているようです.
この手の関数によくあるように,最後の引数でバッファサイズを求めています.
http://groups.google.com/group/comp.os.ms-windows.programmer.win32/browse_thread/thread/07cce218f54e1af0/b7bc61e561ce5b58?lnk=raot

NtQuerySystemInformation Error で検索で検索したら以下のがありましが,
関係なさそうです.
Norton AntiVirus 7.60.926 ?
http://www.scan-associates.net/papers/navx.c

ところで,私の場合,Vistaマシンは1台だけですが(仮想マシンも含めて),Eorror=-1073741820
現れました.それは以下の状況です.XPのマシンではこのテストはしていません.

(1) PCをシャットダウン
(2) PC電源ON
(3) ログイン直後,例のテストプログラムを実行
(4) Eorror=-107374182 となる
(5) ほとんどの場合2回目の起動で Success
    場合によっては2〜3回目

何回かこれを繰り返した結果,エラーにならない場合もありますが,エラーの時が
多いようです.
また,ログインして,タスクバーの右(何ていいましたっけ?),常駐アプリのアイコンが
全て表示されないうち,つまり,システムの起動が完全に終了していない段階で,
テストプログラムを実行すると,何回やってもエラー.
少し時間をおいて,10数回目でSuccessとなりました.

後,ログアウトした(シャットダウンはしない)して再度ログインした場合もエラーと
なることがありました.ただし,こちらの場合は,ほんとにたまにです.

ログインして,しばらくたってからテストしてもエラーになりません.
いずれの場合も,直後だけです.

原因は,ntdll.dll関係のようですね.最初はDelphiを疑ってしまいました.ゴメン!!
ntdll.dllはウィルス攻撃の対象にもなるし,頻繁にMicrosoftがUpdateするので,関係
あるのかも知れません.
現在のところ,こんな状況です.

直接LoadLibraryしたら.. 関係ないかな?
さて,どうやったらいいのかはパニック中(?)です(笑).
CPU使用率算出に,他の方法を考えたのがいいでしょうか>皆様...


歩如  2008-09-13 04:40:08  No: 31794

Mr.XRAY さんどうもありがとうございます。

さて、いろいろ試した結果以下のことがわかりました
私の機械でも Success になる場合があります。
だめな場合ですが
1.IE7 が動作している場合
2.Microsoft Outlook 2003 が動作している場合

さらに調べてみました。

Delphi2007起動中はNGですが、起動後はOKです
新規VCL作成でフォームだけのプログラムを作った場合
IDE上で動作させた場合はNG
実行ファイルで起動した場合はOKです

ところが自作プログラム起動完了じはOKですが、、
処理を行った場合にはNGになります。

プログラム上で処理されている間は使えないような
感じです。


Mr.XRAY  2008-09-13 06:03:42  No: 31795

テストプログラム修正しました.修正点は,以下の通りです.
ちょっとやってみていただけますか.特に急ぎません.
XPではバッファサイズが32KB程度ですが,Vistaでは65KBを超える場合がありました.
(当方の環境では)

(1) ntdll.dllを動的にロード
(2) バッファサイズを取得し,そのサイズで実行

http://mrxray.on.coocan.jp/Others/NtdllTest01.htm


ttt  2008-09-13 06:20:22  No: 31796

せっかくエラーコードを返してくれているので意味を調べてみると……
# for hex 0xc0000004 / decimal -1073741820 :
  STATUS_INFO_LENGTH_MISMATCH  ntstatus.h
# The specified information record length does not match the
# length required for the specified information class.

どうやらバッファのサイズが足りないと言っているようですね。65536でも十分じゃないと。
NtQuerySystemInformationの最後の引数にポインタを指定しておけば
実際に必要なサイズを教えてくれるはずですが、
エラーが出た時には何が入ります?
上のリンク記事みたいに0が返るというオチかもしれませんが。


Mr.XRAY  2008-09-13 06:33:29  No: 31797

いや〜,どうも.

>せっかくエラーコードを返してくれているので意味を調べてみると……

デバッグの基本を忘れていました.
バッファサイズの問題だけであれば助かります(苦笑).


TS  2008-09-14 19:50:21  No: 31798

Mr.XRAYさんの修正  テストプログラムで

WindowsXP Pro SP3 Success BufferSize=76544
WindowsXP Pro SP2 Success BufferSize=75208
WindowsXP Home SP2 Success BufferSize=44480

BufferSizeは実行の度に変化するみたいです。


Mr.XRAY  2008-09-14 23:49:55  No: 31799

>BufferSizeは実行の度に変化するみたいです。

みたいですね.当然といえば当然なんでしょうけど.
PC起動当初は,多くのプロセスが動作するため,私のVista PC起動開始時に
エラーになってしまったんですね.

なんか情けないオチになってしまいました(笑).
後はCPUの使用率の計算方法ですね.


歩如  2008-09-19 03:45:43  No: 31800

Mr.XRAY さんどうもありがとうございました。

>Win32プロセス情報をまるごと取得する方法
これを元に作ってCPUの使用率を出すことができました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加