在做一个监控项目,简单点来说就是A.exe是一个主程序,但有时不知道它会在怎样的一个状态,所以有一个B.exe来对其进行实时监控,获得各项运行状态。试了几种进程通信的方法,觉得有一种真是简单又实用,就是利用FindWindow和SendMessage,特此记下。
首先说FindWindow。 FindWindow返回与指定字符创相匹配的窗口类名或窗口名的最顶层窗口的窗口句柄。函数原型为: C++: HWND FindWindow(LPCTSTR lpClassName,LPCTSTR lpWindowName ); C#: [DllImport("User32.dll", EntryPoint = "FindWindow")] int FindWindow(string lpClassName, string lpWindowName); lpClassName就是窗口类名,大多数情况不会用到它。lpWindowName是窗口名,就是窗口标题,任何一个窗口都有标题,当然也会有相同标题的,那只会找到在z-order最上层的窗口。 再看SendMessage,稍微复杂一点,它是通信的主力军。 SendMessage将指定的消息发送到一个或多个窗口。函数原型为: C++: LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam); C#: [DllImport("User32.dll", EntryPoint = "SendMessage")] int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam); hWnd是接收消息的窗口的句柄。Msg是将被发送的消息。wParam和IParam都是指定附加的消息信息。
这里仅仅介绍怎样利用它们实现进程通信,其实都还有很多功能,不再详述。 要用SendMessage需要知道窗口句柄,这个当然是通过FindWindow,还需要知道是什么消息,在这里用的是0x004A,一般变量命名为WM_COPYDATA,还有就是所要发送的消息信息了,就是具体内容,就需要一个特定的结构COPYDATASTRUCT,原型为: C++: struct COPYDATASTRUCT {ULONG_PTR dwData;DWORD cbData;PVOID lpData;} C#: struct COPYDATASTRUCT{IntPtr dwData;public int cbData;[MarshalAs(UnmanagedType.LPStr)]public string lpData;} 好了这样就可以发送消息到另一个窗口上,代码如下: C++:
Code
void SendFormMessage(LPCTSTR formText, PVOID msg)
  {
HWND hwnd=FindWindow(NULL,formText);
if(hwnd!=0)
 {
COPYDATASTRUCT cd;
cd.dwData = 100;
cd.cbData = 100;
cd.lpData = msg;
SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)(&cd));
}
}
C#:
Code
void sendFormMessage(string formText, string message)
  {
int WINDOW_HANDLER = FindWindow(null, formText);
if (WINDOW_HANDLER != 0)
 {
string SendToPre = message;
byte[] sarr = System.Text.Encoding.Default.GetBytes(SendToPre);
int len = sarr.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpData = SendToPre;
cds.cbData = len + 1;
SendMessage(WINDOW_HANDLER, WM_COPYDATA, 0, ref cds);
}
}
发送完了,那接收窗口就要接收了,怎样接收呢,也很简单还是根据消息0x004A来获得。代码如下: C++:
Code
LONG WINAPI AppWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)//重载窗口消息
  {
COPYDATASTRUCT* pCopyDataStruct;
char buf[];

switch(msg)
 {
case WM_COPYDATA:
 {
pCopyDataStruct = (COPYDATASTRUCT*)lParam;
memset(&buf, 0, sizeof(buf));
memcpy(&buf,pCopyDataStruct->lpData,pCopyDataStruct->cbData);

if (0 == strcmp(buf,""))//在这里判断就可以了
 {}
}
break;
}
return (LONG) DefWindowProc(hwnd,msg,wParam,lParam);
}
举个简单的例子:
向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据. Example: AfxGetMainWindow()-> SendMessage(WM_CLOSE) 还可以创建一个自定义的函数 Terminate Window void Terminate Window(LPCSTR pCaption) { CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption); if (pWnd) pWnd -> SendMessage(WM_CLOSE); } 说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社 "Windows 95 API开发人员指南 "一书有比较详细的介绍,这里就不再多说。
个人觉得,外挂应该多会用到这两个函数的。
| | | |