SetWindowsHookExを使ってWindowsメッセージをフックし、
他のアプリケーションの起動と終了のログを取ろうと思っているのですが、
使用するフックタイプと起動と終了を意味するメッセージの種類がわからずに困っております。
ついでにアプリの起動を検知した後にそのアプリのプロセスIDを取得したいのですがどのようにすればよいでしょうか?
よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

残念ですが、メッセージベースではアプリケーションのロギングはできません。


Win32アプリケーションはメッセージプロシージャを持つ事を義務づけられていません。確かにWindowを表示するときに必要になりますが、バックエンドで動くものについてはなくても動作可能です。

なので完全なロギングがしたいのであればこまめにプロセスリストをポーリングして差分が出た時点でそれをロギングするプログラムをする必要があるでしょう。

プロセスのリスト化についてですが、NT系と9x系で多少違います。
NT系ではPSAPI系API、9x系ではToolHelp系APIを利用する必要があります。
詳細は参照URLやMSDNを参照してください。

参考URL:http://www.microsoft.com/japan/support/kb/articl …
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

QSetWindowsHookEx(グローバルフック)の質問

SetWindowsHookExでグローバルフックして
メッセージをすりかえる事って可能でしょうか?
例えばWM_KEYDOWNが送られてきたら、それを無視して
WM_CLOSEとかえるといった具合に。

試しにWH_CALLWNDPROCで受け取ったメッセージを
書き換えるだけでは無理でした(WindowsXp SP2)

MSDNのWH_CALLWNDPROCRETの関数CallWndRetProcの説明で
「このフックプロシージャは、メッセージを調べることはできますが、変更することはできません。」
となっていました。
ということはWH_CALLWNDPROCのCallWndProcでは変更できるのかな?と思った次第です。

何か情報があれば宜しくお願いします。
(2000では不可だけど98だとできるとか?)

Aベストアンサー

>WH_GETMESSAGEがP「ポストしたメッセージ」
>WH_CALLWNDPROCがS「送出するメッセージ」
>WH_CALLWNDPROCRETがR「送出したメッセージの戻り値」

というか、対象のウィンドウプロシージャにおいて、
P:PostMessageで受け取ったメッセージ
S:SendMessageで受け取ったメッセージ
R:SendMessageの受け取ったときのプロシージャの戻り値

と考えたほうがわかりやすいかと。

#RがSendMessageのみなのは、呼び出し元がPostMessageのときは終了を待たないため。



>>Sendで送られるメッセージもすり替えはたい場合はウィンドウのサブクラス化でしょう。
>>ただし、DLLを対象のプロセスに突っ込む荒業が必要ですが。
>サブクラス化はdllも同じプロセスに属す必要があるんですね。
>この方法についてどこか参考になるサイト、あるいは書籍ってありますか?

ここらへんかな?

http://www.microsoft.com/japan/info/press/JPN_ViewMsPress.asp?Book_id=39&list_id=2

http://ruffnex.oc.to/kenji/text/api_hook/

>WH_GETMESSAGEがP「ポストしたメッセージ」
>WH_CALLWNDPROCがS「送出するメッセージ」
>WH_CALLWNDPROCRETがR「送出したメッセージの戻り値」

というか、対象のウィンドウプロシージャにおいて、
P:PostMessageで受け取ったメッセージ
S:SendMessageで受け取ったメッセージ
R:SendMessageの受け取ったときのプロシージャの戻り値

と考えたほうがわかりやすいかと。

#RがSendMessageのみなのは、呼び出し元がPostMessageのときは終了を待たないため。



>>Sendで送られるメッセージもすり...続きを読む

Qグローバルフック(SetWindowsHookEx)でのEM_REPLACESELの取得について

はじめまして。

グローバルフック(SetWindowsHookEx)を使って別アプリ(exe)がEDITボックスに出力している
文字列を取得しようとしています。
SPY++で確認すると別アプリではEM_REPLACESELを用いていることがわかりました。

フックするDLLを以下のように作成しメッセージをフックすることはできました。

1. フックのセット
  SetWindowsHookEx(WH_CALLWNDPROC, MyHookProc, hInst, dwThreadId);
     // hInst はDllMainでアタッチ時に保存したもの
     // dwThreadIdは別アプリのスレッドID(以下の方法で取得)
     // HWND pWnd = ::FindWindow(NULL, 別アプリのフォームのキャプション) ;
     // HWND pEdt = ::FindWindowEx(pWnd,0,"Edit",0);
     // DWORD dwThreadId= ::GetWindowThreadProcessId(pEdt, NULL);

2. コールバック
  LRESULT CALLBACK MyHookProc(int nCode, WPARAM wp, LPARAM lp)
  {
   if( EM_REPLACESELの判定 ){
     メッセージの保存処理
    }
    return CallNextHookEx(hMyHook, nCode, wp, lp);
  }

上記のコールバックの中で”EM_REPLACESELの判定”をどのようにしたら良いかわからずに困っています。
if分をはずしてファイルにダンプすると何かメッセージが取得できているのは確認できています。
他のサイトを見て、
MSG* pMSG = (MSG*)lp;
として、pMSG->lParam を参照してもEM_REPLACESELになっているメッセージがありませんでした。

何か思いつくことがある方、根本的な間違いがあるという方、
アドバイアスをお願いします。

はじめまして。

グローバルフック(SetWindowsHookEx)を使って別アプリ(exe)がEDITボックスに出力している
文字列を取得しようとしています。
SPY++で確認すると別アプリではEM_REPLACESELを用いていることがわかりました。

フックするDLLを以下のように作成しメッセージをフックすることはできました。

1. フックのセット
  SetWindowsHookEx(WH_CALLWNDPROC, MyHookProc, hInst, dwThreadId);
     // hInst はDllMainでアタッチ時に保存したもの
     // dwThreadIdは別アプリのス...続きを読む

Aベストアンサー

EM_REPLASESELかどうかの判断は pMSG->message だと思いますよ
pMSG->lParamは置換後の文字列のように思います

コールバックのlParamキャストはCWPSTRUCT* または PCWPSTRUCTで行わないといけない気がします
MSG構造体とでは メンバーの並び方も違いますから …

Qアクセス違反でアプリケーションポップアップが出たのにプロセスが終了しない

OS:Windows2000、VC++6.0 の環境です。
自作のアプリケーションにてアクセス違反が発生し、
以下のアプリケーションポップアップが出ました。

アプリケーションポップアップ: AAA.exe - アプリケーション エラー :
"0x0c88026d" の命令が "0x09680048" のメモリを参照しました。
メモリが "written" になることはできませんでした。
プログラムを終了するには [OK] をクリックしてください
プログラムをデバッグするには [キャンセル] をクリックしてください

で、「OK」ボタンを押したのですが、プロセスは終了せず、
処理が続行されてしまいました。
なぜプロセスが終了しないのかがわかりません。
何かの設定でしょうか???

識者の方、ご教授願います。

Aベストアンサー

こんにちは。itohhといいます。

AAA.EXEがどのような処理を行うプログラムなのかわかりませんが。
例えば、
マルチスレッドなどの場合、起こりえるのではないでしょうか?

ただ、わたしもそのような現象は体験したことがありません。

余計なお世話かもしれませんが。(^^;
作成した本人しか使用しないプログラムなら良いですが、そうでない場合は、
例外処理を行ってそのようなダイアログボックスを出さないようにした方が良いですよ。

QUnicode でのWin32アプリのプロセスが終了しません

Visual Studio 2008 のVC++ でのアプリ開発について困っています。
開発環境はOS:Vista Ultimate 64bitです。
開発しようとしているのはWin32プロジェクトです。
先ず以下がソースです。
---
/** @brief メインファイル */
// Option declarations
#define STRICT
#define WIN32_LEAN_AND_MEAN

// Includes
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<tchar.h>
#include<process.h>
#include<windows.h>
#include<windowsx.h>
#include<winerror.h>

// Constance declarations
#define WND_CX (1024)
#define WND_CY (768)
#define ERR_QUIT (-1)

// Structures declarations
typedef struct _winapp
{
HINSTANCE hInst;
HWND hWnd;
TCHAR sTitle[128];
TCHAR sWndClass[128];
}WINAPP, *PWINAPP;

// Prototype declarations
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
HRESULT Init(WINAPP& app);
long Uninit(WINAPP& app);
WPARAM MsgLoop(WINAPP& app);
long Idle(void);

// Global variables
WINAPP g_app;

/** @brief Entry point */
int WINAPI ::_tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR pCmdLine, int shwcmd)
{
// Win32App initialize
::memset(&g_app, 0, sizeof(g_app));
g_app.hInst = hInst;
::_tcscpy_s(g_app.sTitle, sizeof(g_app.sTitle), _T("myapp"));
::_tcscpy_s(g_app.sWndClass, sizeof(g_app.sWndClass), _T("myapp"));

HRESULT hr = ::Init(g_app);
if(FAILED(hr))
return ERR_QUIT;

// Message loop
WPARAM wp = ::MsgLoop(g_app);
// WinApp32 uninitialize
::Uninit(g_app);

return (int)wp;
}

/** @brief Main window procedure */
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch(msg){
case WM_DESTROY:
::PostQuitMessage(0);
g_app.hWnd = NULL;
break;
default:
return ::DefWindowProc(hWnd, msg, wp, lp);
}

return 0;
}

/** @brief Initialize win32 application */
HRESULT Init(WINAPP& app)
{
// Register window class
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)::WndProc;
wc.cbClsExtra = wc.cbWndExtra = 0;
wc.hInstance = app.hInst;
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = app.sWndClass;

if(::RegisterClassEx(&wc)==0)
return ::GetLastError();

// Create main window
RECT rc = { 0, 0, WND_CX, WND_CY};
::AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
g_app.hWnd = ::CreateWindow( app.sWndClass, app.sTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, app.hInst, NULL);
if(app.hWnd==NULL)
return ::GetLastError();

// Show window
::ShowWindow(app.hWnd, SW_SHOWNORMAL);
::UpdateWindow(app.hWnd);

return S_OK;
}

/** @brief Uninitalize win32 application */
long Uninit(WINAPP& app)
{
return ::UnregisterClass(app.sWndClass, app.hInst);
}

/** @brief Message loop */
WPARAM MsgLoop(WINAPP& app)
{
MSG msg = {};
while(msg.message!=WM_QUIT){
if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}else{
// Idle process
if(Idle()==0)
::DestroyWindow(app.hWnd); // Occur error and exit application.
}
}

return msg.wParam;
}

/** @brief Idle process */
long Idle(void)
{
return 1;
}
---
以上がソースなのですがプロジェクトのプロパティの文字セットが
Unicodeだとプロセスが終了しません。
文字セットをマルチバイトに変更するとプロセスは終了します。
なお、メイン関数を終了はしている様子。
どなたか理由がお分かりになる方はおられませんでしょうか?
お手数ですがご回答いただければ幸いです。

Visual Studio 2008 のVC++ でのアプリ開発について困っています。
開発環境はOS:Vista Ultimate 64bitです。
開発しようとしているのはWin32プロジェクトです。
先ず以下がソースです。
---
/** @brief メインファイル */
// Option declarations
#define STRICT
#define WIN32_LEAN_AND_MEAN

// Includes
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<tchar.h>
#include<process.h>
#include<windows.h>
#include<windowsx.h>
#include<winerror.h>

// Con...続きを読む

Aベストアンサー

> while(msg.message!=WM_QUIT){
WM_QUITを処理した後、終了してるみたいですけど、ここが気になります。
WM_QUITの後には、処理すべきメッセージは来ないんですかね。

Win32 アプリケーションの作成 (C++)
http://msdn.microsoft.com/ja-jp/library/bb384843.aspx

QWMIでのプロセスの起動・終了監視について

WMIでのプロセスの起動・終了監視について

●環境
Microsoft VC++ 6.0
Windows XP Pro

●質問
http://mrxray.on.coocan.jp/Delphi/plSamples/902_WMI_ProcessCreateTerminate.htm
の「04_プロセス(アプリケーション)の起動と終了を監視」を参考に、VCに置き換えて作成したのですが途中で詰まってしまいました。

get_Classによる取得までできて、プロセスの作成・終了までは分かるようになったのですが
そのプロセスの情報が取得できません(プロセスIDや名前など)、参考にしたページ(Delphi)ではTargetInstanceから取得できるようなのですが、VCではそのプロパティ(?)が見つからず情報を取得出来ませんでした
どうすれば、プロセスの情報を取得出来るのでしょうか?
よろしくお願いします。

●ソース
_COM_SMARTPTR_TYPEDEF(ISWbemEventSource, __uuidof(ISWbemEventSource));
_COM_SMARTPTR_TYPEDEF(ISWbemObject, __uuidof(ISWbemObject));
_COM_SMARTPTR_TYPEDEF(ISWbemObjectPath, __uuidof(ISWbemObjectPath));

ISWbemEventSourcePtr SWbemEventSourcePtr;
hResult = SWbemServices->ExecNotificationQuery(_bstr_t(L"SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"),
_bstr_t(L"WQL"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&SWbemEventSourcePtr);

while(TRUE)
{
ISWbemObjectPtr SWbemObjectPtr;
hResult = SWbemEventSourcePtr->NextEvent(-1, &SWbemObjectPtr);

CString ccc;
{
ISWbemObjectPathPtr SWbemObjectPathPtr;
hResult = SWbemObjectPtr->get_Path_(&SWbemObjectPathPtr);

CComBSTR ClassString;
hResult = SWbemObjectPathPtr->get_Class(&ClassString);

ccc = ClassString;
}

■■■ここでプロセスに関する情報を取得したい■■■

if(ccc == "__InstanceCreationEvent"){
// プロセス作成
}
else if(ccc == "__InstanceDeletionEvent"){
// プロセス終了
}
}

WMIでのプロセスの起動・終了監視について

●環境
Microsoft VC++ 6.0
Windows XP Pro

●質問
http://mrxray.on.coocan.jp/Delphi/plSamples/902_WMI_ProcessCreateTerminate.htm
の「04_プロセス(アプリケーション)の起動と終了を監視」を参考に、VCに置き換えて作成したのですが途中で詰まってしまいました。

get_Classによる取得までできて、プロセスの作成・終了までは分かるようになったのですが
そのプロセスの情報が取得できません(プロセスIDや名前など)、参考にしたページ(Delphi)ではTargetInstanc...続きを読む

Aベストアンサー

} else if( wcscmp( vtClass.bstrVal, L"__InstanceDeletionEvent" ) == 0 ) {
// Get the value of the Name property
hResult = pwbcoProcess->Get( L"TargetInstance", 0, &vtTargetInstance, 0, 0 );
pwbcoInstance = ( IWbemClassObject * )(vtTargetInstance.ppdispVal);
hResult = pwbcoInstance->Get( L"Caption", 0, &vtCaption, 0, 0 );
wprintf( L"%s : Delete\n", vtCaption.bstrVal );
VariantClear( &vtTargetInstance );
VariantClear( &vtCaption );
iCount++;
}

VariantClear( &vtClass);
}

pNameSpace->Release();
pLocator->Release();
pEnumerator->Release();
pwbcoInstance->Release();
pwbcoProcess->Release();
CoUninitialize();

return 0;
}


/////////////////////////////////////////////////////
// stdafax.h
/////////////////////////////////////////////////////
#pragma once

#define _WIN32_DCOM

#include "targetver.h"

#include <windows.h>
#include <wbemidl.h>
#include <comutil.h>

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


VC++6.0 では、そのままではコンパイルが通らないかもしれません。
その場合は、最新の Windows SDK をインストールすればよいでしょう。

} else if( wcscmp( vtClass.bstrVal, L"__InstanceDeletionEvent" ) == 0 ) {
// Get the value of the Name property
hResult = pwbcoProcess->Get( L"TargetInstance", 0, &vtTargetInstance, 0, 0 );
pwbcoInstance = ( IWbemClassObject * )(vtTargetInstance.ppdispVal);
hResult = pwbcoInstance->Get( L"Caption", 0, &vtCaption, 0, 0 );
wprintf( L"%s : Delete\n", vtCaption.bstrVal );
VariantClear( &vtTargetInstance );
VariantClear( &vtCaption );
iCount++;
}

VariantClear( &vtClass);
}...続きを読む


人気Q&Aランキング

おすすめ情報