寻找进程间通信中使用的 Windows 消息的替代方案

发布于 2024-07-10 08:22:28 字数 1466 浏览 5 评论 0原文

我有一个多线程应用程序(MIDAS),它利用 Windows 消息与其自身进行通信。

MAIN FORM

主窗体接收RDM发送的windows消息 LogData('DataToLog')

因为使用了 Windows 消息,所以它们具有以下属性

  1. 收到的消息是不可分割的
  2. 收到的消息按照发送的顺序排队

问题:

您能否建议一种不使用 Windows 的更好的方法来执行此操作消息?

主窗体代码

const
    UM_LOGDATA      = WM_USER+1002;

type

  TLogData = Record
      Msg        : TMsgNum;
      Src        : Integer;
      Data       : String;
  end;
  PLogData = ^TLogData;


  TfrmMain = class(TForm)
  //  
  private
    procedure LogData(var Message: TMessage);        message UM_LOGDATA;
  public
  //        
  end;


procedure TfrmMain.LogData(var Message: TMessage);
var LData : PLogData;
begin
    LData  :=  PLogData(Message.LParam);
    SaveData(LData.Msg,LData.Src,LData.Data);
    Dispose(LData);
end;

RDM代码

procedure TPostBoxRdm.LogData(DataToLog : String);
var
  WMsg  : TMessage;
  LData : PLogData;
  Msg   : TMsgNum;
begin
  Msg := MSG_POSTBOX_RDM;
  WMsg.LParamLo := Integer(Msg);
  WMsg.LParamHi := Length(DataToLog);
  new(LData);
    LData.Msg    := Msg;
    LData.Src    := 255;
    LData.Data   := DataToLog;
  WMsg.LParam := Integer(LData);
  PostMessage(frmMain.Handle, UM_LOGDATA, Integer(Msg), WMsg.LParam);
end;

编辑:

为什么我想摆脱Windows消息:

  • 我想将应用程序转换为Windows服务
  • 当系统繁忙时 - Windows 消息缓冲区已满并且速度变慢

I a have a multithread application (MIDAS) that makes uses of windows messages to communicate with itself.

MAIN FORM

The main form receives windows messages sent by the RDM
LogData(‘DataToLog’)

Because windows messages are used they have the following attributes

  1. Received messages are Indivisible
  2. Received messages are Queued in the order they are sent

QUESTION:

Can you Suggest a better way doing this without using windows messages ?

MAIN FORM CODE

const
    UM_LOGDATA      = WM_USER+1002;

type

  TLogData = Record
      Msg        : TMsgNum;
      Src        : Integer;
      Data       : String;
  end;
  PLogData = ^TLogData;


  TfrmMain = class(TForm)
  //  
  private
    procedure LogData(var Message: TMessage);        message UM_LOGDATA;
  public
  //        
  end;


procedure TfrmMain.LogData(var Message: TMessage);
var LData : PLogData;
begin
    LData  :=  PLogData(Message.LParam);
    SaveData(LData.Msg,LData.Src,LData.Data);
    Dispose(LData);
end;

RDM CODE

procedure TPostBoxRdm.LogData(DataToLog : String);
var
  WMsg  : TMessage;
  LData : PLogData;
  Msg   : TMsgNum;
begin
  Msg := MSG_POSTBOX_RDM;
  WMsg.LParamLo := Integer(Msg);
  WMsg.LParamHi := Length(DataToLog);
  new(LData);
    LData.Msg    := Msg;
    LData.Src    := 255;
    LData.Data   := DataToLog;
  WMsg.LParam := Integer(LData);
  PostMessage(frmMain.Handle, UM_LOGDATA, Integer(Msg), WMsg.LParam);
end;

EDIT:

Why I want to get rid of the windows messages:

  • I would like to convert the application into a windows service
  • When the system is busy – the windows message buffer gets full and things slows down

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

回首观望 2024-07-17 08:22:28

使用命名管道。 如果您不知道如何使用它们,那么现在是学习的时候了。

使用命名管道,您可以发送任何类型的数据结构(只要服务器和客户端都知道该数据结构是什么)。 我通常使用一组记录来来回发送大量信息。 非常便利。

我使用 Russell Libby 的免费(且开源)命名管道组件。 附带 TPipeServer 和 TPipeClient 可视组件。 它们使命名管道的使用变得异常简单,并且命名管道非常适合进程间通信(IPC)。

您可以在此处获取该组件 。 来源的描述是: // 描述:Delphi 的客户端和服务器命名管道组件集,如
// 一个控制台管道重定向组件。

此外,Russell 帮助我在 Experts-Exchange 上使用该组件的旧版本在控制台应用程序中工作,通过命名管道发送/接收消息。 这可能有助于指导您启动并运行他的组件。 请注意,在 VCL 应用程序或服务中,您不需要像我在这个控制台应用程序中那样编写自己的消息循环。

program CmdClient;
{$APPTYPE CONSOLE}

uses
  Windows, Messages, SysUtils, Pipes;

type
  TPipeEventHandler =  class(TObject)
  public
     procedure  OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
  end;

procedure TPipeEventHandler.OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
begin
  WriteLn('On Pipe Sent has executed!');
end;

var
  lpMsg:         TMsg;
  WideChars:     Array [0..255] of WideChar;
  myString:      String;
  iLength:       Integer;
  pcHandler:     TPipeClient;
  peHandler:     TPipeEventHandler;

begin

  // Create message queue for application
  PeekMessage(lpMsg, 0, WM_USER, WM_USER, PM_NOREMOVE);

  // Create client pipe handler
  pcHandler:=TPipeClient.CreateUnowned;
  // Resource protection
  try
     // Create event handler
     peHandler:=TPipeEventHandler.Create;
     // Resource protection
     try
        // Setup clien pipe
        pcHandler.PipeName:='myNamedPipe';
        pcHandler.ServerName:='.';
        pcHandler.OnPipeSent:=peHandler.OnPipeSent;
        // Resource protection
        try
           // Connect
           if pcHandler.Connect(5000) then
           begin
              // Dispatch messages for pipe client
              while PeekMessage(lpMsg, 0, 0, 0, PM_REMOVE) do DispatchMessage(lpMsg);
              // Setup for send
              myString:='the message I am sending';
              iLength:=Length(myString) + 1;
              StringToWideChar(myString, wideChars, iLength);
              // Send pipe message
              if pcHandler.Write(wideChars, iLength * 2) then
              begin
                 // Flush the pipe buffers
                 pcHandler.FlushPipeBuffers;
                 // Get the message
                 if GetMessage(lpMsg, pcHandler.WindowHandle, 0, 0) then DispatchMessage(lpMsg);
              end;
           end
           else
              // Failed to connect
              WriteLn('Failed to connect to ', pcHandler.PipeName);
        finally
           // Show complete
           Write('Complete...');
           // Delay
           ReadLn;
        end;
     finally
        // Disconnect event handler
        pcHandler.OnPipeSent:=nil;
        // Free event handler
        peHandler.Free;
     end;
  finally
     // Free pipe client
     pcHandler.Free;
  end;

end.

Use Named Pipes. If you don't know how to use them, then now is the time to learn.

With named pipes, you can send any type of data structure (as long as both the server and the client know what that data structure is). I usually use an array of records to send large collections of info back and forth. Very handy.

I use Russell Libby's free (and open-source) named pipe components. Comes with a TPipeServer and a TPipeClient visual component. They make using named pipes incredibly easy, and named pipes are great for inter-process communication (IPC).

You can get the component here. The description from the source is: // Description : Set of client and server named pipe components for Delphi, as
// well a console pipe redirection component.

Also, Russell helped me out on Experts-Exchange with using an older version of this component to work in a console app to send/receive messages over named pipes. This may help as a guide in getting you up and running with using his components. Please note, that in a VCL app or service, you don't need to write your own message loop as I did in this console app.

program CmdClient;
{$APPTYPE CONSOLE}

uses
  Windows, Messages, SysUtils, Pipes;

type
  TPipeEventHandler =  class(TObject)
  public
     procedure  OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
  end;

procedure TPipeEventHandler.OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
begin
  WriteLn('On Pipe Sent has executed!');
end;

var
  lpMsg:         TMsg;
  WideChars:     Array [0..255] of WideChar;
  myString:      String;
  iLength:       Integer;
  pcHandler:     TPipeClient;
  peHandler:     TPipeEventHandler;

begin

  // Create message queue for application
  PeekMessage(lpMsg, 0, WM_USER, WM_USER, PM_NOREMOVE);

  // Create client pipe handler
  pcHandler:=TPipeClient.CreateUnowned;
  // Resource protection
  try
     // Create event handler
     peHandler:=TPipeEventHandler.Create;
     // Resource protection
     try
        // Setup clien pipe
        pcHandler.PipeName:='myNamedPipe';
        pcHandler.ServerName:='.';
        pcHandler.OnPipeSent:=peHandler.OnPipeSent;
        // Resource protection
        try
           // Connect
           if pcHandler.Connect(5000) then
           begin
              // Dispatch messages for pipe client
              while PeekMessage(lpMsg, 0, 0, 0, PM_REMOVE) do DispatchMessage(lpMsg);
              // Setup for send
              myString:='the message I am sending';
              iLength:=Length(myString) + 1;
              StringToWideChar(myString, wideChars, iLength);
              // Send pipe message
              if pcHandler.Write(wideChars, iLength * 2) then
              begin
                 // Flush the pipe buffers
                 pcHandler.FlushPipeBuffers;
                 // Get the message
                 if GetMessage(lpMsg, pcHandler.WindowHandle, 0, 0) then DispatchMessage(lpMsg);
              end;
           end
           else
              // Failed to connect
              WriteLn('Failed to connect to ', pcHandler.PipeName);
        finally
           // Show complete
           Write('Complete...');
           // Delay
           ReadLn;
        end;
     finally
        // Disconnect event handler
        pcHandler.OnPipeSent:=nil;
        // Free event handler
        peHandler.Free;
     end;
  finally
     // Free pipe client
     pcHandler.Free;
  end;

end.
岁月苍老的讽刺 2024-07-17 08:22:28

方案一:自定义消息队列

您可以构建自定义消息队列,将消息推送到队列中,根据业务规则对队列进行排序,并从主线程中弹出队列中的消息进行处理。 使用关键部分进行同步。

选项 2:回调

使用回调在线程之间来回发送数据。 再次,使用临界区进行同步。

Option 1: Custom Message Queue

You can build a custom message queue, and push messages to the queue, sort the queue based on business rules, and pop messages from queue from the main thread for processing. Use a critical section for synchronization.

Option 2: Callbacks

Use callbacks to send data back and forth from the threads. Again, use a critical section for synchronization.

染年凉城似染瑾 2024-07-17 08:22:28

OmniThreadLibraryOtlComm.pas 单元中包含非常高效的消息队列。

目前文档还不是很好(从这里开始)但您始终可以使用论坛

OmniThreadLibrary contains very efficient message queue in OtlComm.pas unit.

Documentation is not very good at the moment (start here) but you can always use the forum.

甜妞爱困 2024-07-17 08:22:28

是的 – Gabr,您可以在服务中使用 Windows 消息。

==============================

在 Windows Vista 之前,您可以将服务配置为与桌面交互。 这使得该服务与登录用户在同一桌面上运行,因此以该用户身份运行的程序可以向服务的窗口发送消息。 不过,Windows Vista 隔离了服务; 他们无法再与任何用户的桌面交互。

===============================

引用 Rob Kennedy 的回答到 'TService 不会处理消息'

但我将无法使用 'frmMain.Handle ' 将消息从 RDM 发布到 Windows Vista 中的主窗体。

我需要做的就是找到一种不同的发布方式和发布方式。 收到消息

Yes – Gabr you can use windows messages in a service.

==============================

Before Windows Vista, you could have configured your service to interact with the desktop. That makes the service run on the same desktop as a logged-in user, so a program running as that user could send messages to your service's windows. Windows Vista isolates services, though; they can't interact with any user's desktop anymore.

=============================

A Quote from Rob Kennedy answer to ‘TService won’t process messages’

But I will not able to use 'frmMain.Handle' to post messages from the RDM to the main form in windows Vista.

All I need to do is find a different way of posting & receive the message

风吹雨成花 2024-07-17 08:22:28

Windows 消息仍然可以在 Windows Vista 中使用! 目前的问题是,vista 中的一项称为用户界面权限隔离 (UIPI) 的技术可防止完整性级别 (IL) 较低的进程向 IL 较高的进程发送消息(例如,Windows 服务具有较高的 IL 和用户权限)模式应用程序具有中等 IL)。

但是,这可以被绕过,并且可以允许中等 IL 应用程序将 wm 发送到高 IL 进程。

维基百科说得最好:

UIPI 不是安全边界,并不旨在防范
所有粉碎攻击。 用户界面辅助功能
应用程序可以通过以下方式绕过 UIPI
将其“uiAccess”值设置为 TRUE
作为其清单文件的一部分。 这
要求应用程序位于
Program Files 或 Windows 目录,如
以及由有效代码签名
签字权,但是这些
需求不一定会停止
恶意软件不尊重它们。

此外,某些消息仍然允许通过,例如
WM_KEYDOWN
,允许较低的 IL
将输入驱动到提升的过程
命令提示符。

最后,函数
ChangeWindowMessageFilter 允许
中等 IL 过程(所有非升高
除 Internet Explorer 之外的进程
保护模式)更改消息
高 IL 进程可以接收
来自较低 IL 过程。 这
有效地允许绕过 UIPI,

除非从 Internet Explorer 运行
或其子进程之一。


Delphi-PRAXIS 的某人(链接是德语。使用 Google 翻译页面)已经解决了这个问题,并使用 ChangeWindowMessageFilter 发布了他们的代码。 我相信他们的问题是 WM_COPYDATA 在 Vista 上无法工作,直到他们修改代码以绕过 WM_COPYDATA 的 UIPI。

原始链接(德语)

unit uMain; 

interface 

uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, ExtCtrls, StdCtrls, uallHook, uallProcess, uallUtil, uallKernel; 

type 
  TfrmMain = class(TForm) 
    lbl1: TLabel; 
    tmrSearchCondor: TTimer; 
    mmo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure tmrSearchCondorTimer(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
  private 
    { Private-Deklarationen } 
    fCondorPID : DWord; 
    fInjected : Boolean; 
    fDontWork : Boolean; 
    procedure SearchCondor; 
    procedure InjectMyFunctions; 
    procedure UnloadMyFunctions; 
    function GetDebugPrivileges : Boolean; 
    procedure WriteText(s : string); 
    procedure WMNOTIFYCD(var Msg: TWMCopyData); message WM_COPYDATA; 
  public 
    { Public-Deklarationen } 
  end; 

var 
  frmMain: TfrmMain; 
  ChangeWindowMessageFilter: function (msg : Cardinal; dwFlag : Word) : BOOL; stdcall; 

implementation 

{$R *.dfm} 

type Tmydata = packed record 
       datacount: integer; 
       ind: boolean; 
     end; 

const cCondorApplication = 'notepad.exe'; 
      cinjComFuntionsDLL = 'injComFunctions.dll'; 

var myData : TMydata; 

procedure TfrmMain.WMNOTIFYCD(var Msg: TWMCopyData); 
begin 
  if Msg.CopyDataStruct^.cbData = sizeof(TMydata) then 
  begin 
    CopyMemory(@myData,Msg.CopyDataStruct^.lpData,sizeof(TMyData)); 
    WriteText(IntToStr(mydata.datacount)) 
  end; 
end; 

procedure TfrmMain.WriteText(s : string); 
begin 
  mmo1.Lines.Add(DateTimeToStr(now) + ':> ' + s); 
end; 

procedure TfrmMain.InjectMyFunctions; 
begin 
  if not fInjected then begin 
    if InjectLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)) then fInjected := True; 
  end; 
end; 

procedure TfrmMain.UnloadMyFunctions; 
begin 
  if fInjected then begin 
    UnloadLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)); 
    fInjected := False; 
  end; 
end; 

procedure TfrmMain.SearchCondor; 
begin 
  fCondorPID := FindProcess(cCondorApplication); 
  if fCondorPID <> 0 then begin 
    lbl1.Caption := 'Notepad is running!'; 
    InjectMyFunctions; 
  end else begin 
    lbl1.Caption := 'Notepad isn''t running!'; 
  end; 
end; 

procedure TfrmMain.FormDestroy(Sender: TObject); 
begin 
  UnloadMyFunctions; 
end; 

function TfrmMain.GetDebugPrivileges : Boolean; 
begin 
  Result := False; 
  if not SetDebugPrivilege(SE_PRIVILEGE_ENABLED) then begin 
    Application.MessageBox('No Debug rights!', 'Error', MB_OK); 
  end else begin 
    Result := True; 
  end; 
end; 

procedure TfrmMain.FormCreate(Sender: TObject); 
begin 
  @ChangeWindowMessageFilter := GetProcAddress(LoadLibrary('user32.dll'), 'ChangeWindowMessageFilter'); 
  ChangeWindowMessageFilter(WM_COPYDATA, 1); 
  fInjected := False; 
  fDontWork := not GetDebugPrivileges; 
  tmrSearchCondor.Enabled := not fDontWork; 
end; 

procedure TfrmMain.tmrSearchCondorTimer(Sender: TObject); 
begin 
  tmrSearchCondor.Enabled := False; 
  SearchCondor; 
  tmrSearchCondor.Enabled := True; 
end; 

end.

Windows Messages CAN still be used in Windows Vista! The issue at hand is that a technology in vista called User Interface Privilege Isolation (UIPI) prevents processes with a lower integrity level (IL) from sending messages to a proccess with a high IL (e.g. a windows service has a high IL and user-mode apps have medium IL).

However, this can be bypassed and medium IL apps can be allowed to send wm's to high IL processes.

Wikipedia says it best:

UIPI is not a security boundary, and does not aim to protect against
all shatter attacks. UI Accessibility
Applications can bypass UIPI by
setting their "uiAccess" value to TRUE
as part of their manifest file. This
requires the application to be in the
Program Files or Windows directory, as
well as to be signed by a valid code
signing authority, but these
requirements will not necessarily stop
malware from respecting them.

Additionally, some messages are still allowed through, such as
WM_KEYDOWN
, which allows a lower IL
process to drive input to an elevated
command prompt.

Finally, the function
ChangeWindowMessageFilter allows a
medium IL process
(all non-elevated
processes except Internet Explorer
Protected Mode) to change the messages
that a high IL process can receive
from a lower IL process. This
effectively allows bypassing UIPI,

unless running from Internet Explorer
or one of its child processes.

Someone over at Delphi-PRAXIS (link is in German. Use Google to Translate the page) has already tackled this problem and posted their code using ChangeWindowMessageFilter. I believe their issue is that WM_COPYDATA would not work on Vista until they modified their code to bypass UIPI for WM_COPYDATA.

Original Link (German)

unit uMain; 

interface 

uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, ExtCtrls, StdCtrls, uallHook, uallProcess, uallUtil, uallKernel; 

type 
  TfrmMain = class(TForm) 
    lbl1: TLabel; 
    tmrSearchCondor: TTimer; 
    mmo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure tmrSearchCondorTimer(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
  private 
    { Private-Deklarationen } 
    fCondorPID : DWord; 
    fInjected : Boolean; 
    fDontWork : Boolean; 
    procedure SearchCondor; 
    procedure InjectMyFunctions; 
    procedure UnloadMyFunctions; 
    function GetDebugPrivileges : Boolean; 
    procedure WriteText(s : string); 
    procedure WMNOTIFYCD(var Msg: TWMCopyData); message WM_COPYDATA; 
  public 
    { Public-Deklarationen } 
  end; 

var 
  frmMain: TfrmMain; 
  ChangeWindowMessageFilter: function (msg : Cardinal; dwFlag : Word) : BOOL; stdcall; 

implementation 

{$R *.dfm} 

type Tmydata = packed record 
       datacount: integer; 
       ind: boolean; 
     end; 

const cCondorApplication = 'notepad.exe'; 
      cinjComFuntionsDLL = 'injComFunctions.dll'; 

var myData : TMydata; 

procedure TfrmMain.WMNOTIFYCD(var Msg: TWMCopyData); 
begin 
  if Msg.CopyDataStruct^.cbData = sizeof(TMydata) then 
  begin 
    CopyMemory(@myData,Msg.CopyDataStruct^.lpData,sizeof(TMyData)); 
    WriteText(IntToStr(mydata.datacount)) 
  end; 
end; 

procedure TfrmMain.WriteText(s : string); 
begin 
  mmo1.Lines.Add(DateTimeToStr(now) + ':> ' + s); 
end; 

procedure TfrmMain.InjectMyFunctions; 
begin 
  if not fInjected then begin 
    if InjectLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)) then fInjected := True; 
  end; 
end; 

procedure TfrmMain.UnloadMyFunctions; 
begin 
  if fInjected then begin 
    UnloadLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)); 
    fInjected := False; 
  end; 
end; 

procedure TfrmMain.SearchCondor; 
begin 
  fCondorPID := FindProcess(cCondorApplication); 
  if fCondorPID <> 0 then begin 
    lbl1.Caption := 'Notepad is running!'; 
    InjectMyFunctions; 
  end else begin 
    lbl1.Caption := 'Notepad isn''t running!'; 
  end; 
end; 

procedure TfrmMain.FormDestroy(Sender: TObject); 
begin 
  UnloadMyFunctions; 
end; 

function TfrmMain.GetDebugPrivileges : Boolean; 
begin 
  Result := False; 
  if not SetDebugPrivilege(SE_PRIVILEGE_ENABLED) then begin 
    Application.MessageBox('No Debug rights!', 'Error', MB_OK); 
  end else begin 
    Result := True; 
  end; 
end; 

procedure TfrmMain.FormCreate(Sender: TObject); 
begin 
  @ChangeWindowMessageFilter := GetProcAddress(LoadLibrary('user32.dll'), 'ChangeWindowMessageFilter'); 
  ChangeWindowMessageFilter(WM_COPYDATA, 1); 
  fInjected := False; 
  fDontWork := not GetDebugPrivileges; 
  tmrSearchCondor.Enabled := not fDontWork; 
end; 

procedure TfrmMain.tmrSearchCondorTimer(Sender: TObject); 
begin 
  tmrSearchCondor.Enabled := False; 
  SearchCondor; 
  tmrSearchCondor.Enabled := True; 
end; 

end.
毅然前行 2024-07-17 08:22:28

madExcept 库等的创建者提供了可以用来代替 Windows 消息的 IPC 功能。

http://help.madshi.net/IPC.htm

我曾经开发过一个 Windows 屏幕保护程序阶段,我想让我的屏幕保护程序向另一个程序发送一些通知,当屏幕保护程序处于活动状态时,我无法获取在两个应用程序之间工作的窗口消息。

我用上面提到的IPC功能替换了它。

做了一份款待。

The creators of the madExcept library etc provide IPC functionality which can be used instead of Windows messages.

http://help.madshi.net/IPC.htm

I developed a Windows screensaver at one stage, and I wanted to get my screensaver to send some notification to another program, and while the screensaver was active, I was unable to get window messages to work between the two apps.

I replaced it with the IPC functionality mentioned above.

Worked a treat.

孤云独去闲 2024-07-17 08:22:28

我将此库用于 IPc(使用共享内存+互斥体):
http://17slon.com/gp/gp/gpsync.htm

它有 TGpMessageQueueReader和 TGpMessageQueueWriter。 在名称前面使用“Global\”,这样当用户登录时,您可以使用它在 Windows 服务和“Service GUI Helper”之间进行通信。(Vista 需要 Global\ 前缀,因为会话安全环,也适用于 Windows XP/2003 用户会话之间)。

它非常快,多线程等。我会使用这个而不是 WM_COPYDATA (如果你经常使用它,速度慢且开销很大,但对于小事情消息可以是好的)

I use this library for IPc (uses shared memory + mutex):
http://17slon.com/gp/gp/gpsync.htm

It has TGpMessageQueueReader and TGpMessageQueueWriter. Use "Global\" in front of the name, so you can use it to communicate between a Windows Service and a "Service GUI Helper" when a user logs in. (the Global\ prefix is needed for Vista because of session security rings, but also for Windows XP/2003 between user sessions).

It is very fast, multithreaded, etc. I would use this one instead of WM_COPYDATA (slow & much overhead if you use it a lot, but for small things messages can be OK)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文