如何在两个Delphi应用程序之间传递字符串

3

可能是重复问题:
寻找替代Windows消息的进程间通信
进程间通信

我有一个运行的Delphi 7应用程序,公开了一个类型库。TLB公开的函数之一是ProcessFile(fileName:string)。当调用该函数时,我希望正在运行的Windows服务(也是Delphi 7应用程序)得到通知,说明已调用此事件以及文件名是什么。

如果您对如何实现此操作有任何想法,将不胜感激。我已经尝试通过使用注册表和txt文件进行更改回调来完成此操作,但无论哪种方式,我偶尔都会丢失要处理的文件,因为可以每秒钟调用多次ProcessFile方法。

谢谢!


Ken,我认为他正在寻找TLB的ProcessFile方法的钩子。但是标题暗示了其他事情。 - alzaimar
1
将字符串发送到命名管道。 - David Heffernan
2
@alzaimar 无论他在寻找什么,IPC都是唯一的答案。 - David Heffernan
检查由Iztok Kacin开发的开源、即插即用的应用程序间通信库Cronis IPC。据我所知,该库基于命名管道。 - Edwin Yip
1个回答

7

管道非常适合这项工作。您可以在服务端实现一个管道读取线程,并通过客户端的ProcessFile方法发送相应的字符串数据到管道中。

以下是一个快速、简单且无错误检查的管道使用示例:

管道服务器

var
  Form1: TForm1;
  t: TReadpipe;

  h: THandle;
  msg: string;

const BufSize=512;

implementation

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  chandle: THandle;
begin
  t.Terminate;

  chandle := CreateFile('\\.\pipe\myNamedPipe', GENERIC_WRITE, 0, nil,
    OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0);
  CloseHandle(chandle);

  t.WaitFor;
  t.Free;
  CloseHandle(h);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  t := Treadpipe.Create(false);
end;

{ TReadPipe }

procedure TReadPipe.Execute;
var
  buf: array [0 .. BufSize-1] of char;
  read: cardinal;
begin
  while not Terminated do
  begin
    h := CreateNamedPipe('\\.\pipe\myNamedPipe', PIPE_ACCESS_DUPLEX,
      PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT,
      PIPE_UNLIMITED_INSTANCES, BufSize, BufSize, 0, nil);

    ConnectNamedPipe(h, nil);

    if Terminated then
      break;

    msg := '';

    repeat
      FillChar(buf, BufSize, #0);
      ReadFile(h, buf[0], BufSize, read, nil);

      msg := msg + Copy(buf, 0, read);
    until GetLastError <> ERROR_MORE_DATA;

    if msg <> '' then
      Synchronize(
        procedure
        begin
          form1.Memo1.Lines.Add(msg)
        end);
  end;

  DisconnectNamedPipe(h);
end;

PipeClient

var
  Form1: TForm1;
  i: Integer = 0;
  pipe: THandle;

const
  BufSize = 512;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  buf: array [0 .. BufSize - 1] of char;
  written: Cardinal;
  str: pchar;
begin
  pipe := CreateFile('\\.\pipe\myNamedPipe', GENERIC_WRITE, 0, nil,
    OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0);

  if pipe = INVALID_HANDLE_VALUE then
    Halt;

  inc(i);
  str := pchar('someStr' + inttostr(i));
  fillchar(buf, BufSize, #0);
  move(str[0], buf[0], Length(str) * Sizeof(char));
  WriteFile(pipe, buf[0], Length(str) * Sizeof(char), written, nil);

  CloseHandle(pipe);
end;

同样要记住,管道作为先进先出队列(FIFO)进行操作。

你不需要保护管道吗? - David Heffernan
这是一个简单管道使用的快速示例。用户确实应该采取安全措施。 - Hasan Manzak
嗨@The_aLiEn,我看了你的建议并会遵循它,但在你的服务器代码片段中,你调用了CtreateNamedPipe('\.\pipe\myNamedPipe', PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT,PIPE_UNLIMITED_INSTANCES, BufSize, BufSize, 0, nil);以及ConnectNamedPipe(h, nil);这些库或Delphi单元是什么?我的猜测是它们来自第三方(希望是开源的)?如果是这样,请提供一个链接,让我可以获取它们或提供这些过程的代码。谢谢!David - daktmacfan
它们不是来自第三方单元,它们是纯WinAPI ;) 而且文档完全免费,因为它是Windows SDK,显然。你找不到这些API的任何洞察代码,因为Windows不是开源软件,但在SDK中有很多东西解释了如何使用、如何不使用以及这些API和参数的说明。这里 是相应的文档。 - Hasan Manzak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接