進程之間通訊的幾種方法:
在Windows程序中,各個進程之間常常需要交換數據,進行數據通訊。常用的方法有
使用內存映射文件
通過共享內存DLL共享內存
使用SendMessage向另一進程發送WM_COPYDATA消息
比起前兩種的復雜實現來,WM_COPYDATA消息無疑是一種經濟實惠的一中方法。WM_COPYDATA消息的主要目的是允許在進程間傳遞只讀數據。Windows在通過WM_COPYDATA消息傳遞期間,不提供繼承同步方式。SDK文檔推薦用戶使用SendMessage函數,接受方在數據拷貝完成前不返回,這樣發送方就不可能刪除和修改數據。注意,接受方在DefWndProc事件中,來處理這條消息。由於中文編碼是兩個字節,所以傳遞中文時候字節長度要搞清楚。
用WM_COPYDATA的前提:
1,知道接收消息進程的句柄。
2,接收消息進程重載了WM_COPYDATA消息映射,能對其做出反應(否則不是發送端自作多情了?)
前幾天寫程序用到WM_COPYDATA進行進程間通信,但是接收方怎么也收不到消息。調試發現找到的窗口句柄是沒有問題的,查看MSDN也沒有什么提示,百思不得其解。后來看了一些示例代碼,發現不同之處是我的SendMessage調用中wParam和lParam參數都是0,因為我只是需要通過WM_COPYDATA消息通知一下接收程序即可,不用傳遞任何數據。試着將這兩個參數改為非空,接收方就可以收到消息了。總結結論為:wParam參數是否為0沒有影響,但是lParam參數必須為非空,即必須指向一個有效的COPYDATASTRUCT結構體。原因是什么呢?查了一些資料發現,SendMessage(WM_COPYDATA)底層是通過文件映射(File Mapping)完成的,大概流程是發送方線程根據COPYDATASTRUCT結構體中的傳遞數據信息,在共享內存中進行數據復制,接收方線程則會到共享內存中讀取數據進行處理。因此如果指向COPYDATASTRUCT結構的指針為空的話,流程是無法進行的,所以接收方也理所當然收不到消息。
procedure TForm1.Button2Click(Sender: TObject);
var
Receiver: THandle;
buffer: array[0..1023] of char;
Data: TCopyDataStruct;
begin
Receiver := FindWindow('TReceiverForm', nil);
if Receiver > 0 then
begin
StrPLCopy(@buffer, Edit1.Text, 1024); // Assumes message in Editbox
Data.dwData := 0;
Data.cbData := 1024;
Data.lpData := @buffer;
SendMessage(Receiver, WM_COPYDATA, 0, LongInt(@Data));
end;
end;
type
TForm1 = class(TForm)
{ ... }
private
{ ... }
protected
procedure WmCopyData(var Msg: TMessage); message WM_COPYDATA;
public
{ ... }
end;
procedure TForm1.WmCopyData(var Msg: TMessage);
begin
ShowMessage(
'This message sent:' + #13 +
string(PChar(PCopyDataStruct(Msg.LParam)^.lpData))
);
end;
參考:http://www.xuebuyuan.com/976757.html
http://blog.csdn.net/iseekcode/article/details/4821082
