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}

    WIN8系统调用此函数打开文件无效。
    
    执行成功会返回应用程序句柄
    返回的HINSTANCE可以将它转换为一个整数(%d),并比较它的值大于还是小于32或比较它的错误代码
    返回值大于32表示执行成功
    返回值小于32表示执行错误
    返回值可能的错误有: = 0 {内存不足}
      ERROR_FILE_NOT_FOUND = 2; {文件名错误}
      ERROR_PATH_NOT_FOUND = 3; {路径名错误}
      ERROR_BAD_FORMAT = 11; {EXE 文件无效}
      SE_ERR_SHARE = 26; {发生共享错误}
      SE_ERR_ASSOCINCOMPLETE = 27; {文件名不完全或无效}
      SE_ERR_DDETIMEOUT = 28; {超时}
      SE_ERR_DDEFAIL = 29; {DDE 事务失败}
      SE_ERR_DDEBUSY = 30; {正在处理其他 DDE 事务而不能完成该 DDE 事务}
      SE_ERR_NOASSOC = 31; {没有相关联的应用程序}

     

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2021-10-12 16:38  耗喜天涯  阅读(1002)  评论(0编辑  收藏  举报