ページ 11

実行中のアプリケーション情報の取得について

Posted: 2012年4月13日(金) 21:14
by se_user
実行中のアプリケーションの情報を取得したいんですが、具体的に申しますと
起動中アプリケーションが読み込んでいるスレッド等の情報をすべて表示させることは可能でしょうか?

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月14日(土) 11:44
by softya(ソフト屋)
詳しくはないですが、processExplolerとかでは表示できているので取得する手段はあると思います。
というよりprocessExplolerではダメですか?

「Process Explorer」
http://technet.microsoft.com/en-us/sysi ... s/bb896653

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月14日(土) 12:11
by se_user
softya(ソフト屋) さんが書きました:詳しくはないですが、processExplolerとかでは表示できているので取得する手段はあると思います。
というよりprocessExplolerではダメですか?

「Process Explorer」
http://technet.microsoft.com/en-us/sysi ... s/bb896653
返信ありがとうございます。
自作したいんですが、関数だけ抜き出したりできませんか・・・

http://processhacker.sourceforge.net/do ... ource.html

こちらのページにソースがありました。

プロジェクト化されているのですが、

コード:

    PhAddTreeNewColumn(hwnd, PHTHTLC_STARTADDRESS, TRUE, L"Start Address", 180, PH_ALIGN_LEFT, 3, 0);

コード:

  case PHTHTLC_STARTADDRESS:
                PhSwapReference(&node->StartAddressText, threadItem->StartAddressString);
                getCellText->Text = PhGetStringRef(node->StartAddressText);
この部分のみを利用したいのですが、可能でしょうか?

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月14日(土) 12:20
by YuO
プロセスやスレッドなどの列挙は,Tool Help Libraryを使うのが基本です。
ただし,スレッドの開始アドレスはこの方法では取得できないようです。

WMIを探すと,Win32_thread classがあって,ここにはStartAddressというメンバがあります。
ただし,型がint_ptrのような記述では無くuint32と書かれているため,x64環境で正しく取得できるのか疑問がありますが。

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月14日(土) 12:41
by softya(ソフト屋)
「Process Explorer」はオープンソースではないので参考に出来ませんね。
YuOさんの方法が参考になるのでは?

[追記]
あれ?オープンソースでした? → 別の似たようなツールですね。
ソースがあるのなら試してみれば良いのでは?

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月14日(土) 12:45
by se_user
YuO さんが書きました:プロセスやスレッドなどの列挙は,Tool Help Libraryを使うのが基本です。
ただし,スレッドの開始アドレスはこの方法では取得できないようです。

WMIを探すと,Win32_thread classがあって,ここにはStartAddressというメンバがあります。
ただし,型がint_ptrのような記述では無くuint32と書かれているため,x64環境で正しく取得できるのか疑問がありますが。
Win32_thread classの使用方法を教えてください。
識別子が見つからないので、おそらくなにらかのincludeが必要かと思われます。

コード:

Win32_Thread(
  string   Caption,
  string   CreationClassName,
  string   CSCreationClassName,
  string   CSName,
  string   Description,
  uint64   ElapsedTime,
  uint16   ExecutionState,
  string   Handle,
  datetime InstallDate,
  uint64   KernelModeTime,
  string   Name,
  string   OSCreationClassName,
  string   OSName,
  uint32   Priority,
  uint32   PriorityBase,
  string   ProcessCreationClassName,
  string   ProcessHandle,
  uint32   StartAddress,
  string   Status,
  uint32   ThreadState,
  uint32   ThreadWaitReason,
  uint64   UserModeTime);

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月14日(土) 14:48
by softya(ソフト屋)
Win32_thread classが含まれるWMIはcom系なので次のような操作が必要です。

「C++ で WMI クラスを使う « re-Think things」
http://togarasi.wordpress.com/2009/12/2 ... %E3%81%86/
ATL のスマートポインタを使ってますが好きなスマートポインタに置き換えて下さい。

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月15日(日) 01:23
by たろ
NtQuerySystemInformationで取得できたような・・と思ったのでやってみました。
自分の環境(WinXP Home SP3)でしか確認していませんが、ご参考までに。。
ただProcess Explorerが表示するStartAddressの内容は取れないようにも見えます。
スレッドIDやスレッドの数は合っているようですが。

コード:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

//--------------------------------------------------------------------------------------------------
//
//    NTDLL関数戻り値
//    NTSTATUS_SUCCESS=成功、NTSTATUS_XXX=エラー。ntstatus.hに定義。
//    必要なものを SDK/v6.0A/Include/ntstatus.hからコピー
//
#ifndef NTSTATUS
#define NTSTATUS LONG
#endif
#define STATUS_SUCCESS                ((NTSTATUS)0x00000000L) // ntsubauth
#define STATUS_INFO_LENGTH_MISMATCH   ((NTSTATUS)0xC0000004L)

typedef LONG KPRIORITY;

typedef struct {
    HANDLE    UniqueProcess;
    HANDLE    UniqueThread;
} CLIENT_ID, *PCLIENT_ID;

typedef enum {
    Executive           = 0,
    FreePage            = 1,
    PageIn              = 2,
    PoolAllocation      = 3,
    // 使わないので途中省略
    WrRundown           = 36,
    MaximumWaitReason   = 37
} KWAIT_REASON, *PKWAIT_REASON;

// SDK/v6.0A/Include/winternl.h
typedef struct {
    USHORT    Length;
    USHORT    MaximumLength;
    PWSTR     Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct {
    UINT64        KernelTime;
    UINT64        UserTime;
    UINT64        CreateTime;
    ULONG         WaitTime;
    PVOID         StartAddress;
    CLIENT_ID     ClientId;
    KPRIORITY     Priority;
    LONG          BasePriority;
    ULONG         ContextSwitches;
    ULONG         ThreadState;
    KWAIT_REASON  WaitReason;
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;

//
//    SYSTEM_PROCESS_INFORMATION構造体は、最後のメンバSYSTEM_THREAD_INFORMATIONが可変長で、
//    NtQuerySystemInformationでは可変長のものがつながった配列を取得する。次の配列エントリ
//    はNextEntryOffsetメンバでわかる。
//    これ以外の構造体は Process Hacker 2.x ソースも参考・流用。
//
typedef struct {
    ULONG           NextEntryOffset;                // 次エントリオフセット
    BYTE            Reserved1[28];
    UINT64          CreateTime;
    UINT64          UserTime;                       // ユーザ時間(100ナノ秒単位)
    UINT64          KernelTime;                     // カーネル時間(100ナノ秒単位)
    UNICODE_STRING  ImageName;                      // プロセス名("notepad.exe"など)
    KPRIORITY       BasePriority;
    HANDLE          UniqueProcessId;                // プロセスID
    HANDLE          InheritedFromUniqueProcessId;   // 親プロセスID
    ULONG           HandleCount;                    // ハンドル数
    ULONG           SessionId;
    ULONG_PTR       PageDirectoryBase;
    SIZE_T          PeakVirtualSize;                // ピーク仮想メモリサイズ
    SIZE_T          VirtualSize;                    // 仮想メモリサイズ
    ULONG           PageFaultCount;
    SIZE_T          PeakWorkingSetSize;             // ピークワーキングセットサイズ
    SIZE_T          WorkingSetSize;                 // ワーキングセットサイズ
    SIZE_T          QuotaPeakPagedPoolUsage;
    SIZE_T          QuotaPagedPoolUsage;
    SIZE_T          QuotaPeakNonPagedPoolUsage;
    SIZE_T          QuotaNonPagedPoolUsage;
    SIZE_T          PagefileUsage;
    SIZE_T          PeakPagefileUsage;
    SIZE_T          PrivatePageCount;               // プライベートページ数
    UINT64          ReadOperationCount;             // I/O読み取り
    UINT64          WriteOperationCount;            // I/O書き込み
    UINT64          OtherOperationCount;            // I/Oその他
    UINT64          ReadTransferCount;              // I/O読み取りバイト数
    UINT64          WriteTransferCount;             // I/O書き込みバイト数
    UINT64          OtherTransferCount;             // I/Oその他バイト数
    SYSTEM_THREAD_INFORMATION Threads[1];           // スレッド情報(可変)
} SYSTEM_PROCESS_INFORMATION;

//
// SDK/v6.0A/Include/winternl.h
//
typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBasicInformation = 0,
    SystemPerformanceInformation = 2,
    SystemTimeOfDayInformation = 3,
    SystemProcessInformation = 5,
    SystemProcessorPerformanceInformation = 8,
    SystemInterruptInformation = 23,
    SystemExceptionInformation = 33,
    SystemRegistryQuotaInformation = 37,
    SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;

//
//    NtQuerySystemInformation関数ポインタ型
//
typedef NTSYSAPI NTSTATUS (NTAPI *PNtQuerySystemInformation)
(
    IN   SYSTEM_INFORMATION_CLASS  SystemInformationClass,
    OUT  PVOID                     SystemInformation,
    IN   ULONG                     SystemInformationLength,
    OUT  PULONG                    ReturnLength OPTIONAL
);
//
//    SYSTEM_PROCESS_INFORMATION構造体配列で次の構造体ポインタを取得する関数マクロ
//
#define IS_LAST_PROCESS(p)            ( (p)->NextEntryOffset==0 )
#define PROCESS_INFORMATION_NEXT(p)   \
        (SYSTEM_PROCESS_INFORMATION*)(IS_LAST_PROCESS(p)? 0 : (((ULONG_PTR)(p)) + (p)->NextEntryOffset))


//
//  SYSTEM_PROCESS_INFORMATION構造体のスレッド数を返す
//
UINT32
ThreadCount( SYSTEM_PROCESS_INFORMATION* pi, ULONG_PTR limit )
{
    SYSTEM_THREAD_INFORMATION* thread = pi->Threads;
    UINT32 count = 0;

    while( (ULONG_PTR)thread < limit )
    {
        thread++;
        count++;
    }
    if( (ULONG_PTR)thread > limit )
    {
        // 最後の構造体がサイズ不足?
        count--;
    }
    return count;
}

int
_tmain( void )
{
    HINSTANCE ntdll = LoadLibrary( _T("ntdll.dll") );
    if( ntdll )
    {
        PNtQuerySystemInformation pNtSysInfo = (PNtQuerySystemInformation)GetProcAddress(ntdll,"NtQuerySystemInformation");
        if( pNtSysInfo )
        {
            SYSTEM_PROCESS_INFORMATION* spi = NULL;
            NTSTATUS status;
            ULONG size = 0;

         retry:
            status = pNtSysInfo( SystemProcessInformation, spi, size, &size );
            switch( status ) {
            case STATUS_SUCCESS:
            {
                // 成功
                SYSTEM_PROCESS_INFORMATION* pi = spi;
                while( pi )
                {
                    SYSTEM_PROCESS_INFORMATION* next = PROCESS_INFORMATION_NEXT( pi );
                    UINT32 count, n;

                    if( pi->ImageName.Buffer )
                        wprintf(L"%u %s\r\n", pi->UniqueProcessId, pi->ImageName.Buffer);
                    else
                        wprintf(L"%u %s\r\n", pi->UniqueProcessId, L"System Idle Process");

                    if( next )
                        count = ThreadCount( pi, (ULONG_PTR)next );
                    else
                        count = ThreadCount( pi, (ULONG_PTR)spi + size );

                    for( n=0; n<count; n++ )
                    {
                        SYSTEM_THREAD_INFORMATION* th = pi->Threads + n;
                        wprintf(L"   [%u] %p %u %u\r\n",
                                n+1, th->StartAddress, th->ClientId.UniqueProcess, th->ClientId.UniqueThread);
                    }
                    pi = next;
                }

                HeapFree( GetProcessHeap(), 0, spi );
                break;
            }
            case STATUS_INFO_LENGTH_MISMATCH:
                // バッファサイズ不足、再確保してリトライ
                if( spi ) HeapFree( GetProcessHeap(), 0, spi );
                spi = (SYSTEM_PROCESS_INFORMATION*)HeapAlloc( GetProcessHeap(), 0, size );
                if( !spi ) break;
                goto retry;

            default:
                // エラー
                if( spi ) HeapFree( GetProcessHeap(), 0, spi );
                spi = NULL;
                break;
            }
            pNtSysInfo = NULL;
        }
        FreeLibrary( ntdll );
        ntdll = NULL;
    }
    return 0;
}

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月15日(日) 02:59
by se_user
返信ありがとうございます。


>ただProcess Explorerが表示するStartAddressの内容は取れないようにも見えます。
>スレッドIDやスレッドの数は合っているようですが。
Process Hacker のソースを参考にStart Addressまでは見れないですかね・・・・
thrdlist.cに書いてあると思うんですけど

Re: 実行中のアプリケーション情報の取得について

Posted: 2012年4月15日(日) 10:56
by softya(ソフト屋)
se_user さんが書きました:返信ありがとうございます。


>ただProcess Explorerが表示するStartAddressの内容は取れないようにも見えます。
>スレッドIDやスレッドの数は合っているようですが。
Process Hacker のソースを参考にStart Addressまでは見れないですかね・・・・
thrdlist.cに書いてあると思うんですけど
誰も使ったことがない機能だと思いますので、ご自分でまず試してみてはどうでしょうか?
それとも誰かに全部プログラムを組んで欲しいのでしょうか? それだと丸投げでフォーラムルール違反になりますが。