如何从一个Delphi程序实例发送字符串到另一个实例?

时间:2022-03-25 07:11:59

What is the best and easiest way to send a string from one instance of my program to another instance of my program? The receiving program has to execute a procedure, using the received string as a parameter.

从我的程序的一个实例发送字符串到我的程序的另一个实例的最佳和最简单的方法是什么?接收程序必须使用接收的字符串作为参数来执行过程。

I started reading about DDE but I got confused. What other options do I have, and what is the easiest way to implement this?

我开始阅读DDE,但我感到困惑。我还有什么其他选择,实现这个的最简单方法是什么?

8 个解决方案

#1


Use named Pipes, but I would recommend Russell Libby's named Pipe components. There is a TPipeClient and TPipeServer component.

使用命名管道,但我会推荐Russell Libby的命名管道组件。有一个TPipeClient和TPipeServer组件。

As of (2013-10-04) Francoise Piette and arno.garrels@gmx.de updated this source code to compile with Delphi 7 to XE5 (earlier versions may compile however untested) and put it here: http://www.overbyte.be/frame_index.html?redirTo=/blog_source_code.html

截至(2013-10-04),Francoise Piette和arno.garrels@gmx.de更新了这个源代码,用Delphi 7编译成XE5(早期版本可以编译但未经测试)并将其放在此处:http://www.overbyte .BE / frame_index.html?redirTo = / blog_source_code.html

These 2 components make using named pipes incredibly easy, and named pipes are great for inter-process communication (IPC).

这两个组件使命名管道非常容易使用,命名管道非常适合进程间通信(IPC)。

His website is here. Look for "Pipes.zip". The description from the source is: // Description : Set of client and server named pipe components for Delphi, as // well a console pipe redirection component.

他的网站在这里。寻找“Pipes.zip”。源代码的描述是://描述:Delphi的客户端和服务器命名管道组件集合,以及//控制台管道重定向组件。

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.

此外,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.

#2


I use named pipes for this, it was the easiest one I found. I'll post the code when I get home from work.

我为此使用命名管道,这是我发现的最简单的管道。我下班回家时会发布代码。

Here's an article on how to use it in delphi: http://www.delphi3000.com/articles/article_2918.asp?SK=

这是一篇关于如何在德尔福中使用它的文章:http://www.delphi3000.com/articles/article_2918.asp?SC =

There's a million solutions to this by the way, all of them seem to be annoying. Pipes is the best one I've found so far.

顺便提一下,有一百万个解决方案,所有这些解决方案似乎很烦人。管道是迄今为止我发现的最好的管道。

Here's the code, sorry about the delay. You should check out the Pipe library mentioned by Mick too. The thing I've done here was a pretty quick experiment. Please note that it was made in Delphi 2009.

这是代码,对延迟感到抱歉。您应该查看Mick提到的管道库。我在这里做的事情是一个非常快速的实验。请注意,它是在Delphi 2009中制作的。

unit PetriW.Pipes;

interface

uses
  Windows,
  Classes,
  Forms,
  SyncObjs,
  SysUtils
  ;

type
  TPBPipeServerReceivedDataEvent = procedure(AData: string) of object;

  TPBPipeServer = class
  private
    type
      TPBPipeServerThread = class(TThread)
      private
        FServer: TPBPipeServer;
      protected
      public
        procedure Execute; override;

        property  Server: TPBPipeServer read FServer;
      end;
  private
    FOnReceivedData: TPBPipeServerReceivedDataEvent;
    FPath: string;
    FPipeHandle: THandle;
    FShutdownEvent: TEvent;
    FThread: TPBPipeServerThread;
  protected
  public
    constructor Create(APath: string);
    destructor Destroy; override;

    property  Path: string read FPath;

    property  OnReceivedData: TPBPipeServerReceivedDataEvent read FOnReceivedData write FOnReceivedData;
  end;

  TPBPipeClient = class
  private
    FPath: string;
  protected
  public
    constructor Create(APath: string);
    destructor Destroy; override;

    property  Path: string read FPath;

    procedure SendData(AData: string); overload;
    class procedure SendData(APath, AData: string); overload;
  end;

implementation

const
  PIPE_MESSAGE_SIZE = $20000;

{ TPipeServer }

constructor TPBPipeServer.Create(APath: string);
begin
  FPath := APath;

  FShutdownEvent := TEvent.Create(nil, True, False, '');

  FPipeHandle := CreateNamedPipe(
    PWideChar(FPath),
    PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED,
    PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT,
    PIPE_UNLIMITED_INSTANCES,
    SizeOf(Integer),
    PIPE_MESSAGE_SIZE,
    NMPWAIT_USE_DEFAULT_WAIT,
    nil
  );

  if FPipeHandle = INVALID_HANDLE_VALUE then
    RaiseLastOSError;

  FThread := TPBPipeServerThread.Create(true);
  FThread.FreeOnTerminate := false;
  FThread.FServer := self;
  FThread.Resume;
end;

destructor TPBPipeServer.Destroy;
begin
  FShutdownEvent.SetEvent;
  FreeAndNil(FThread);
  CloseHandle(FPipeHandle);
  FreeAndNil(FShutdownEvent);

  inherited;
end;

{ TPipeServer.TPipeServerThread }

procedure TPBPipeServer.TPBPipeServerThread.Execute;
var
  ConnectEvent, ReadEvent: TEvent;
  events: THandleObjectArray;
  opconnect, opread: TOverlapped;
  Signal: THandleObject;
  buffer: TBytes;
  bytesRead, error: Cardinal;
begin
  inherited;

  //SetThreadName('TPBPipeServer.TPBPipeServerThread');

  ConnectEvent := TEvent.Create(nil, False, False, '');
  try
    setlength(events, 2);
    events[1] := Server.FShutdownEvent;

    FillMemory(@opconnect, SizeOf(TOverlapped), 0);
    opconnect.hEvent := ConnectEvent.Handle;

    while not Terminated do
    begin
      ConnectNamedPipe(Server.FPipeHandle, @opconnect);

      events[0] := ConnectEvent;
      THandleObject.WaitForMultiple(events, INFINITE, False, Signal);
      if Signal = ConnectEvent then
      try
        // successful connect!
        ReadEvent := TEvent.Create(nil, True, False, '');
        try
          FillMemory(@opread, SizeOf(TOverlapped), 0);
          opread.hEvent := ReadEvent.Handle;
          setlength(buffer, PIPE_MESSAGE_SIZE);

          if not ReadFile(Server.FPipeHandle, buffer[0], PIPE_MESSAGE_SIZE, bytesRead, @opread) then
          begin
            error := GetLastError;
            if error = ERROR_IO_PENDING then
            begin
              if not GetOverlappedResult(Server.FPipeHandle, opread, bytesRead, True) then
                error := GetLastError
              else
                error := ERROR_SUCCESS;
            end;
            if error = ERROR_BROKEN_PIPE then
              // ignore, but discard data
              bytesRead := 0
            else if error = ERROR_SUCCESS then
              // ignore
            else
              RaiseLastOSError(error);
          end;

          if (bytesRead > 0) and Assigned(Server.OnReceivedData) then
            Server.OnReceivedData(TEncoding.Unicode.GetString(buffer, 0, bytesRead));

          // Set result to 1
          PInteger(@buffer[0])^ := 1;
          if not WriteFile(Server.FPipeHandle, buffer[0], SizeOf(Integer), bytesRead, @opread) then
          begin
            error := GetLastError;
            if error = ERROR_IO_PENDING then
            begin
              if not GetOverlappedResult(Server.FPipeHandle, opread, bytesRead, True) then
                error := GetLastError
              else
                error := ERROR_SUCCESS;
            end;
            if error = ERROR_BROKEN_PIPE then
              // ignore
            else if error = ERROR_SUCCESS then
              // ignore
            else
              RaiseLastOSError(error);
          end;
        finally
          FreeAndNil(ReadEvent);
        end;
      finally
        DisconnectNamedPipe(Server.FPipeHandle);
      end
      else if Signal = Server.FShutdownEvent then
      begin
        // server is shutting down!
        Terminate;
      end;
    end;
  finally
    FreeAndNil(ConnectEvent);
  end;
end;

{ TPBPipeClient }

constructor TPBPipeClient.Create(APath: string);
begin
  FPath := APath;
end;

destructor TPBPipeClient.Destroy;
begin

  inherited;
end;

class procedure TPBPipeClient.SendData(APath, AData: string);
var
  bytesRead: Cardinal;
  success: Integer;
begin
  if not CallNamedPipe(PWideChar(APath), PWideChar(AData), length(AData) * SizeOf(Char), @success, SizeOf(Integer), bytesRead, NMPWAIT_USE_DEFAULT_WAIT) then
    RaiseLastOSError;
end;

procedure TPBPipeClient.SendData(AData: string);
var
  bytesRead: Cardinal;
  success: boolean;
begin
  if not CallNamedPipe(PWideChar(FPath), PWideChar(AData), length(AData) * SizeOf(Char), @success, SizeOf(Integer), bytesRead, NMPWAIT_USE_DEFAULT_WAIT) then
    RaiseLastOSError;
end;

end.

Here's how I send something:

这是我发送的东西:

TPBPipeClient.SendData('\\.\pipe\pipe server E5DE3B9655BE4885ABD5C90196EF0EC5', 'HELLO');

Here's how I read something:

这是我读的东西:

procedure TfoMain.FormCreate(Sender: TObject);
begin
  PipeServer := TPBPipeServer.Create('\\.\pipe\pipe server E5DE3B9655BE4885ABD5C90196EF0EC5');
  PipeServer.OnReceivedData := PipeDataReceived;
end;

procedure TfoMain.PipeDataReceived(AData: string);
begin
  if AData = 'HELLO' then
    // do something, but note that you're not in the main thread, you're in the pipe server thread
end;

#3


For very short messages, WM_COPYDATA is probably the easiest. Other than that, there is PetriW's suggestion of named pipes, or sockets.

对于非常短的消息,WM_COPYDATA可能是最简单的。除此之外,PetriW建议使用命名管道或插座。

#4


See JclAppInstances in the JCL.

请参阅JCL中的JclAppInstances。

#5


Get a look at ZeroMQ. If you got the thoughts behind the architecture it may dramatically change the way you think. As far as I had a walkthrough they have libraries for many programming languages, including Delphi. But I had not a chance to try it.

看看ZeroMQ。如果你了解了架构背后的想法,它可能会大大改变你的思维方式。至于我有一个演练,他们有许多编程语言的库,包括Delphi。但我没有机会尝试它。

ZeroMQ

Here is Delphi port of the library.

这是图书馆的Delphi端口。

#6


Check Cromis.IPC, internally it uses named pipes, but provides a much easier API, and it's compatible with recent Delphi versions.

检查Cromis.IPC,在内部使用命名管道,但提供了更简单的API,并且它与最近的Delphi版本兼容。

#7


I suggest TMappedFile - more efficient than named pipes.

我建议TMappedFile - 比命名管道更有效。

#8


I use InterAppComm and it's very good.

我使用InterAppComm,非常好。

It sends data between two or more applications. It can send strings, integers and other data types.

它在两个或多个应用程序之间发送数据。它可以发送字符串,整数和其他数据类型。

#1


Use named Pipes, but I would recommend Russell Libby's named Pipe components. There is a TPipeClient and TPipeServer component.

使用命名管道,但我会推荐Russell Libby的命名管道组件。有一个TPipeClient和TPipeServer组件。

As of (2013-10-04) Francoise Piette and arno.garrels@gmx.de updated this source code to compile with Delphi 7 to XE5 (earlier versions may compile however untested) and put it here: http://www.overbyte.be/frame_index.html?redirTo=/blog_source_code.html

截至(2013-10-04),Francoise Piette和arno.garrels@gmx.de更新了这个源代码,用Delphi 7编译成XE5(早期版本可以编译但未经测试)并将其放在此处:http://www.overbyte .BE / frame_index.html?redirTo = / blog_source_code.html

These 2 components make using named pipes incredibly easy, and named pipes are great for inter-process communication (IPC).

这两个组件使命名管道非常容易使用,命名管道非常适合进程间通信(IPC)。

His website is here. Look for "Pipes.zip". The description from the source is: // Description : Set of client and server named pipe components for Delphi, as // well a console pipe redirection component.

他的网站在这里。寻找“Pipes.zip”。源代码的描述是://描述:Delphi的客户端和服务器命名管道组件集合,以及//控制台管道重定向组件。

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.

此外,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.

#2


I use named pipes for this, it was the easiest one I found. I'll post the code when I get home from work.

我为此使用命名管道,这是我发现的最简单的管道。我下班回家时会发布代码。

Here's an article on how to use it in delphi: http://www.delphi3000.com/articles/article_2918.asp?SK=

这是一篇关于如何在德尔福中使用它的文章:http://www.delphi3000.com/articles/article_2918.asp?SC =

There's a million solutions to this by the way, all of them seem to be annoying. Pipes is the best one I've found so far.

顺便提一下,有一百万个解决方案,所有这些解决方案似乎很烦人。管道是迄今为止我发现的最好的管道。

Here's the code, sorry about the delay. You should check out the Pipe library mentioned by Mick too. The thing I've done here was a pretty quick experiment. Please note that it was made in Delphi 2009.

这是代码,对延迟感到抱歉。您应该查看Mick提到的管道库。我在这里做的事情是一个非常快速的实验。请注意,它是在Delphi 2009中制作的。

unit PetriW.Pipes;

interface

uses
  Windows,
  Classes,
  Forms,
  SyncObjs,
  SysUtils
  ;

type
  TPBPipeServerReceivedDataEvent = procedure(AData: string) of object;

  TPBPipeServer = class
  private
    type
      TPBPipeServerThread = class(TThread)
      private
        FServer: TPBPipeServer;
      protected
      public
        procedure Execute; override;

        property  Server: TPBPipeServer read FServer;
      end;
  private
    FOnReceivedData: TPBPipeServerReceivedDataEvent;
    FPath: string;
    FPipeHandle: THandle;
    FShutdownEvent: TEvent;
    FThread: TPBPipeServerThread;
  protected
  public
    constructor Create(APath: string);
    destructor Destroy; override;

    property  Path: string read FPath;

    property  OnReceivedData: TPBPipeServerReceivedDataEvent read FOnReceivedData write FOnReceivedData;
  end;

  TPBPipeClient = class
  private
    FPath: string;
  protected
  public
    constructor Create(APath: string);
    destructor Destroy; override;

    property  Path: string read FPath;

    procedure SendData(AData: string); overload;
    class procedure SendData(APath, AData: string); overload;
  end;

implementation

const
  PIPE_MESSAGE_SIZE = $20000;

{ TPipeServer }

constructor TPBPipeServer.Create(APath: string);
begin
  FPath := APath;

  FShutdownEvent := TEvent.Create(nil, True, False, '');

  FPipeHandle := CreateNamedPipe(
    PWideChar(FPath),
    PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED,
    PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT,
    PIPE_UNLIMITED_INSTANCES,
    SizeOf(Integer),
    PIPE_MESSAGE_SIZE,
    NMPWAIT_USE_DEFAULT_WAIT,
    nil
  );

  if FPipeHandle = INVALID_HANDLE_VALUE then
    RaiseLastOSError;

  FThread := TPBPipeServerThread.Create(true);
  FThread.FreeOnTerminate := false;
  FThread.FServer := self;
  FThread.Resume;
end;

destructor TPBPipeServer.Destroy;
begin
  FShutdownEvent.SetEvent;
  FreeAndNil(FThread);
  CloseHandle(FPipeHandle);
  FreeAndNil(FShutdownEvent);

  inherited;
end;

{ TPipeServer.TPipeServerThread }

procedure TPBPipeServer.TPBPipeServerThread.Execute;
var
  ConnectEvent, ReadEvent: TEvent;
  events: THandleObjectArray;
  opconnect, opread: TOverlapped;
  Signal: THandleObject;
  buffer: TBytes;
  bytesRead, error: Cardinal;
begin
  inherited;

  //SetThreadName('TPBPipeServer.TPBPipeServerThread');

  ConnectEvent := TEvent.Create(nil, False, False, '');
  try
    setlength(events, 2);
    events[1] := Server.FShutdownEvent;

    FillMemory(@opconnect, SizeOf(TOverlapped), 0);
    opconnect.hEvent := ConnectEvent.Handle;

    while not Terminated do
    begin
      ConnectNamedPipe(Server.FPipeHandle, @opconnect);

      events[0] := ConnectEvent;
      THandleObject.WaitForMultiple(events, INFINITE, False, Signal);
      if Signal = ConnectEvent then
      try
        // successful connect!
        ReadEvent := TEvent.Create(nil, True, False, '');
        try
          FillMemory(@opread, SizeOf(TOverlapped), 0);
          opread.hEvent := ReadEvent.Handle;
          setlength(buffer, PIPE_MESSAGE_SIZE);

          if not ReadFile(Server.FPipeHandle, buffer[0], PIPE_MESSAGE_SIZE, bytesRead, @opread) then
          begin
            error := GetLastError;
            if error = ERROR_IO_PENDING then
            begin
              if not GetOverlappedResult(Server.FPipeHandle, opread, bytesRead, True) then
                error := GetLastError
              else
                error := ERROR_SUCCESS;
            end;
            if error = ERROR_BROKEN_PIPE then
              // ignore, but discard data
              bytesRead := 0
            else if error = ERROR_SUCCESS then
              // ignore
            else
              RaiseLastOSError(error);
          end;

          if (bytesRead > 0) and Assigned(Server.OnReceivedData) then
            Server.OnReceivedData(TEncoding.Unicode.GetString(buffer, 0, bytesRead));

          // Set result to 1
          PInteger(@buffer[0])^ := 1;
          if not WriteFile(Server.FPipeHandle, buffer[0], SizeOf(Integer), bytesRead, @opread) then
          begin
            error := GetLastError;
            if error = ERROR_IO_PENDING then
            begin
              if not GetOverlappedResult(Server.FPipeHandle, opread, bytesRead, True) then
                error := GetLastError
              else
                error := ERROR_SUCCESS;
            end;
            if error = ERROR_BROKEN_PIPE then
              // ignore
            else if error = ERROR_SUCCESS then
              // ignore
            else
              RaiseLastOSError(error);
          end;
        finally
          FreeAndNil(ReadEvent);
        end;
      finally
        DisconnectNamedPipe(Server.FPipeHandle);
      end
      else if Signal = Server.FShutdownEvent then
      begin
        // server is shutting down!
        Terminate;
      end;
    end;
  finally
    FreeAndNil(ConnectEvent);
  end;
end;

{ TPBPipeClient }

constructor TPBPipeClient.Create(APath: string);
begin
  FPath := APath;
end;

destructor TPBPipeClient.Destroy;
begin

  inherited;
end;

class procedure TPBPipeClient.SendData(APath, AData: string);
var
  bytesRead: Cardinal;
  success: Integer;
begin
  if not CallNamedPipe(PWideChar(APath), PWideChar(AData), length(AData) * SizeOf(Char), @success, SizeOf(Integer), bytesRead, NMPWAIT_USE_DEFAULT_WAIT) then
    RaiseLastOSError;
end;

procedure TPBPipeClient.SendData(AData: string);
var
  bytesRead: Cardinal;
  success: boolean;
begin
  if not CallNamedPipe(PWideChar(FPath), PWideChar(AData), length(AData) * SizeOf(Char), @success, SizeOf(Integer), bytesRead, NMPWAIT_USE_DEFAULT_WAIT) then
    RaiseLastOSError;
end;

end.

Here's how I send something:

这是我发送的东西:

TPBPipeClient.SendData('\\.\pipe\pipe server E5DE3B9655BE4885ABD5C90196EF0EC5', 'HELLO');

Here's how I read something:

这是我读的东西:

procedure TfoMain.FormCreate(Sender: TObject);
begin
  PipeServer := TPBPipeServer.Create('\\.\pipe\pipe server E5DE3B9655BE4885ABD5C90196EF0EC5');
  PipeServer.OnReceivedData := PipeDataReceived;
end;

procedure TfoMain.PipeDataReceived(AData: string);
begin
  if AData = 'HELLO' then
    // do something, but note that you're not in the main thread, you're in the pipe server thread
end;

#3


For very short messages, WM_COPYDATA is probably the easiest. Other than that, there is PetriW's suggestion of named pipes, or sockets.

对于非常短的消息,WM_COPYDATA可能是最简单的。除此之外,PetriW建议使用命名管道或插座。

#4


See JclAppInstances in the JCL.

请参阅JCL中的JclAppInstances。

#5


Get a look at ZeroMQ. If you got the thoughts behind the architecture it may dramatically change the way you think. As far as I had a walkthrough they have libraries for many programming languages, including Delphi. But I had not a chance to try it.

看看ZeroMQ。如果你了解了架构背后的想法,它可能会大大改变你的思维方式。至于我有一个演练,他们有许多编程语言的库,包括Delphi。但我没有机会尝试它。

ZeroMQ

Here is Delphi port of the library.

这是图书馆的Delphi端口。

#6


Check Cromis.IPC, internally it uses named pipes, but provides a much easier API, and it's compatible with recent Delphi versions.

检查Cromis.IPC,在内部使用命名管道,但提供了更简单的API,并且它与最近的Delphi版本兼容。

#7


I suggest TMappedFile - more efficient than named pipes.

我建议TMappedFile - 比命名管道更有效。

#8


I use InterAppComm and it's very good.

我使用InterAppComm,非常好。

It sends data between two or more applications. It can send strings, integers and other data types.

它在两个或多个应用程序之间发送数据。它可以发送字符串,整数和其他数据类型。