Delphi跨进程间消息通讯
多个不同进程之间的消息传递有多种方式,但若传递的信息量不大,借用WINDOW的消息机制不失为一种简易有效的方法,
01. 注意 PostMessage 与 SendMessage 之间的异同;
PostMessage: 异步消息模式,负责向指定的句柄发送消息,不等待结果直接返回;
一般适用于进程内的信息传递处理;(如多个不同线程向主线程汇报状态和结果等);
SendMessage:同步消息模式,负责缶指定的句柄发送消息,等消息处理完了再返回;
可以完成PostMessage相应的功能,同时可借用 TCopyDataStruct 达成跨进程的消息处理;
02. 消息发送 (在与设备对接过程中,因涉及到许多不同规则的自定义数据内容,所以习惯使用字节和指针做数据传递了,
而不直接使用PAnsichar这种对#0有特殊要求的指针)
1 procedure SendDaemonMsg(pMsg: string; pHWND: THandle); 2 var 3 CopyDataStruct: TCopyDataStruct; 4 tmpInfos: TBytes; 5 begin 6 if pHWND = 0 then 7 Exit; 8 tmpInfos := BytesOf(pMsg); 9 // 10 CopyDataStruct.lpData := @tmpInfos[0]; { 要发送的字符串, #0 表示 PChar 结束} 11 CopyDataStruct.dwData := WM_COPYDATA; { 指定消息类型 } 12 CopyDataStruct.cbData := Length(tmpInfos); { 指定要发送的数据的大小 } 13 SendMessage(pHWND, WM_COPYDATA, 0, Integer(@CopyDataStruct)); { 发送 数据在 LParam 上} 14 end;
消息接收:
1 procedure WMCopyData(var Message: TWMCopyData); 2 var 3 tmpInfos: TBytes; 4 tmpJson: string; 5 begin 6 SetLength(tmpInfos, Message.CopyDataStruct.cbData); 7 Move(Message.CopyDataStruct.lpData^, tmpInfos[0], Message.CopyDataStruct.cbData); 8 tmpJson := StringOf(tmpInfos); 9 mmo_1.Lines.Append(tmpJson); 10 end;
对于消息处理函数的定义,也可以将Message定义为TMessage,
1 procedure WMCopyData(var Msg: TMessage); 2 var 3 cdds : TcopyDataStruct; 4 begin 5 if msg.Msg = WM_COPYDATA then 6 begin 7 cdds := PcopyDataStruct(Msg.LParam)^; 8 //之后再依据cdds 来处理业务 (后面与procedure WMCopyData(var Message: TWMCopyData); 一致)
9 end;
10 end;
03. 关于软件运行权限对消息传递的影响(依据实测情况总结)
为便于理解,将二个不同的程序定义为: PA, PB
测试情况如下: (详情见Demo: >>> 21013.Daemon )
04. 若在PA,PB之间的某个程序,有信息等待的处理情况
如: PA 为守护程序时,给PB发消息,PB在收到消息后,再给PA传个消息,
若PA需要依据PB传递的数据的情况分情况处理后续内容;
对于这种需求,需要注意几点:
a. PB在接收到消息后,最好新开线程来向PA发消息;
b. PA发消息后,如果此时在等待PB的消息数据,(例如:使用了TEvent来等信号)
这个时候,PA在向PB发消息的时候,最好也是走线程,要不然,会出现信号等待超时等问题;
05. 关于 守护程序 与 服务器程序 在相互守护时,对另一程序的路径问题的说明
>> 使用绝对路径, 而不是只使用 程序名称 xxx.exe;
>> 原因说明:
a. 在窗口模式下,绝对路径与文件名称这二种方式,都可以达到相互守护的效果;
b. 在电脑重新开机后,若只有程序名称,无法有效的守护;问题点在于:文件不存在;
若提供绝对路径,可以很好的达成相互守护;
>>关于 ShellExecute函数原型及参数含义如下:
1 ShellExecute( 2 hWnd: HWND; {指定父窗口句柄} 3 Operation: PChar; {指定动作, 譬如: open、runas、print、edit、explore、find[2] } 4 FileName: PChar; {指定要打开的文件或程序} 5 Parameters: PChar; {给要打开的程序指定参数; 如果打开的是文件这里应该是 nil} 6 Directory: PChar; {缺省目录} 7 ShowCmd: Integer {打开选项} 8 ): HINST;
ShowCmd 参数可选值:
SW_HIDE = 0; {隐藏}
SW_SHOWNORMAL = 1; {用最近的大小和位置显示, 激活}
SW_NORMAL = 1; {同 SW_SHOWNORMAL}
SW_SHOWMINIMIZED = 2; {最小化, 激活}
SW_SHOWMAXIMIZED = 3; {最大化, 激活}
SW_MAXIMIZE = 3; {同 SW_SHOWMAXIMIZED}
SW_SHOWNOACTIVATE = 4; {用最近的大小和位置显示, 不激活}
SW_SHOW = 5; {同 SW_SHOWNORMAL}
SW_MINIMIZE = 6; {最小化, 不激活}
SW_SHOWMINNOACTIVE = 7; {同 SW_MINIMIZE}
SW_SHOWNA = 8; {同 SW_SHOWNOACTIVATE}
SW_RESTORE = 9; {同 SW_SHOWNORMAL}
SW_SHOWDEFAULT = 10; {同 SW_SHOWNORMAL}
SW_MAX = 10; {同 SW_SHOWNORMAL}