進程之間通訊的幾種方法:
在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