Как передать строку между двумя приложениями Delphi

Возможный дубликат:
Поиск альтернативы сообщениям Windows, используемым в межпроцессном взаимодействии
Inter -обработка связи

У меня запущено приложение Delphi 7, которое предоставляет библиотеку типов. Одной из функций, предоставляемых TLB, является ProcessFile(fileName: string). Когда эта функция вызывается, я хотел бы, чтобы запущенная служба Windows (также приложение Delphi 7) получала уведомление о том, что это событие было вызвано и каково имя файла.

Любые мысли о том, как это сделать, будут высоко оценены. Я уже пытался сделать это с помощью измененных обратных вызовов, используя реестр и текстовый файл, но в любом случае я иногда теряю файл, который должен быть обработан, поскольку этот метод ProcessFile может вызываться много раз в секунду.

Спасибо!


person daktmacfan    schedule 20.11.2012    source источник
comment
Кен, я думаю, он ищет зацепку в методе ProcessFile TLB. Заголовок подразумевает другое.   -  person alzaimar    schedule 20.11.2012
comment
Отправить строку по именованному каналу   -  person David Heffernan    schedule 20.11.2012
comment
@alzaimar Независимо от того, что он ищет, IPC - единственный ответ   -  person David Heffernan    schedule 20.11.2012
comment
Ознакомьтесь с готовой к использованию коммуникационной библиотекой между приложениями с открытым исходным кодом Изтока Качина, которая называется Кронис IPC. IIRC, он основан на именованных каналах   -  person Edwin Yip    schedule 20.11.2012


Ответы (1)


Трубы идеально подходят для этой работы. Вы можете реализовать поток чтения каналов на стороне службы и отправлять соответствующие строковые данные через канал в методе ProcessFile на стороне клиента.

Быстрый и простой пример использования Pipe без ошибок:

Трубный сервер

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.

person Hasan Manzak    schedule 20.11.2012
comment
Не нужно ли закреплять трубу? - person David Heffernan; 20.11.2012
comment
Это быстрый пример использования простой трубы. Пользователь действительно должен принять меры безопасности. - person Hasan Manzak; 20.11.2012
comment
Привет, @The_aLiEn, я смотрю ваше предложение и могу следовать ему, но во фрагменте кода вашего сервера вы вызываете CtreateNamedPipe('\\.\pipe\myNamedPipe', PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE или PIPE_READMODE_MESSAGE или PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BufSize, BufSize, 0, nil) ; а также ConnectNamedPipe(h, nil); Частью какой библиотеки или модулей Delphi они являются? Я предполагаю, что они являются чем-то сторонним (надеюсь, с открытым исходным кодом)? Если да, не могли бы вы предоставить ссылку, где я могу их получить, или предоставить код для этих процедур? Спасибо! Дэйвид - person daktmacfan; 21.11.2012
comment
Они не от стороннего модуля, это чистый WinAPI ;) И документация совершенно бесплатна, так как это, очевидно, Windows SDK. Вы не можете найти какой-либо код понимания этих API, поскольку Windows не является программным обеспечением с открытым исходным кодом, но в SDK есть много-много всего, что объясняет, как использовать, как не использовать, а также объяснения этих API и параметров. Вот соответствующую документацию. - person Hasan Manzak; 21.11.2012