Einzelnen Beitrag anzeigen

Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#1

Interprozesskommunikation mitttels Memory Mapped Files

  Alt 7. Mär 2005, 22:45
Wie man zwischen zwei selbst geschriebenen Anwendungen kommunizieren kann, zeigt uns Luckie mit seinem folgenden Code:

Sender-Anwendung
Delphi-Quellcode:
{
  Author  : Michael Puff - [url]http://developer.luckie-online.de[/url]
  Date    : 2005-03-07
  License : PUBLIC DOMAIN
}



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TTSender = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TMyData = record
    Zeichenkette: string[255];
    Zahl: Integer;
    BoolVar: Boolean;
  end;
  PMyData = ^TMyData;

const
  WM_MMFNOTIFY = WM_USER + 1;

var
  TSender: TTSender;

implementation

{$R *.dfm}

function WriteToMMF(MyData: PMyData; Filename: string; hWnd: THandle): DWORD;
var
  dwResult: DWORD;
  hFileMapping: THandle;
  Mem: PMyData;
begin
  Mem := nil;
  dwResult := 0;
  hFileMapping := CreateFileMapping(INVALID_HANDLE_VALUE, nil,
    PAGE_READWRITE, 0, sizeof(TMyData), PChar(Filename));
  if hFileMapping <> 0 then
  begin
    Mem := MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
    if Assigned(Mem) then
    begin
      CopyMemory(Mem, MyData, sizeof(TMyData));
      UnmapViewOfFile(Mem);
      SendMessage(hWnd, WM_MMFNOTIFY, 0, 0);
      CloseHandle(hFileMapping);
    end;
  end
  else
    dwResult := GetLastError;
  result := dwResult;
end;

procedure TTSender.Button1Click(Sender: TObject);
var
  s: string;
  MyData: PMyData;
  dwResult: DWORD;
  hReceiver: THandle;
begin
  SetLastError(0);
  hReceiver := FindWindow(nil, 'TReceiver');
  if hReceiver <> 0 then
  begin
    MyData := GetMemory(sizeof(TMyData));
    try
      if Assigned(MyData) then
      begin
        s := 'Hello world';
        MyData.Zeichenkette := PChar(s);
        MyData.Zahl := -3;
        MyData.BoolVar := True;
        dwResult := WriteToMMF(MyData, 'MyFileMapping', hReceiver);
        if dwResult <> ERROR_SUCCESS then
          ShowMessage(SysErrorMessage(dwResult));
      end;
    finally
      FreeMemory(MyData);
    end;
  end
  else
    ShowMessage(SysErrorMessage(GetLastError));
end;

end.
Empfänger-Anwendung
Delphi-Quellcode:
{
  Author  : Michael Puff - [url]http://developer.luckie-online.de[/url]
  Date    : 2005-03-07
  License : PUBLIC DOMAIN
}



unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  WM_MMFNOTIFY = WM_USER + 1;

type
  TTReceiver = class(TForm)
    Edit1: TEdit;
    CheckBox1: TCheckBox;
    Edit2: TEdit;
  private
    { Private declarations }
    procedure WMMMFNOTIFY(var msg: TMessage); message WM_MMFNOTIFY;
  public
    { Public declarations }
  end;

type
  TMyData = record
    Zeichenkette: string[255];
    Zahl: Integer;
    BoolVar: Boolean;
  end;
  PMyData = ^TMyData;

var
  TReceiver: TTReceiver;

implementation

{$R *.dfm}

function ReadFromMMF(Filename: string): TMyData;
var
  hFileMapping: THandle;
  Mem: PMyData;
begin
  hFileMapping := CreateFileMapping(INVALID_HANDLE_VALUE, nil,
    PAGE_READONLY, 0, sizeof(TMyData), PChar(Filename));
  if hFileMapping <> 0 then
  begin
    Mem := MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if Assigned(Mem) then
    begin
      result.Zeichenkette := Mem.Zeichenkette;
      result.Zahl := Mem.Zahl;
      result.BoolVar := Mem.BoolVar;
      UnmapViewOfFile(Mem);
    end;
  end
end;

procedure TTReceiver.WMMMFNOTIFY(var msg: TMessage);
var
  MyData: TMyData;
begin
  MyData := ReadFromMMF('MyFileMapping');
  Edit1.Text := MyData.Zeichenkette;
  CheckBox1.Checked := MyData.BoolVar;
  Edit2.Text := IntToStr(MyData.Zahl);
end;

end.

Zitat von Luckie:
Will man allerdings nur einen String übergeben und sollte dieser länger als 255 Zeichen sein, dann ist Sir Thornberrys Methode wohl die bessere.
SirThornberrys Methode ist folgende und sendet hier einen Text von dem einen Programmg zum anderen:

Sender-Anwendung
Delphi-Quellcode:
procedure SendText(Text: string);
var LHandle: Cardinal;
begin
  fFileHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, length(Edit1.Text) + 1, 'WunschName');
  if fFileHandle <> 0 then
  begin
    FSpeicher := MapViewOfFile(fFileHandle, FILE_MAP_WRITE, 0, 0, 0);
    StrCopy(FSpeicher, PChar(Text));
    UnmapViewOfFile(FSpeicher);
    LHandle := FindWindow('TAnwendungA', nil);
    if LHandle <> 0 then
    begin
      SendMessage(LHandle, WM_USER + 5, 0, 0);
    end;
    CloseHandle(fFileHandle);
  end;
end;
Empfänger-Anwendung
Delphi-Quellcode:
procedure ReceiveText(var AMessage: TMessage): string;
var LSpeicher: PChar;
    LDest: String;
begin
  fFileHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 500, 'WunschName');
  if fFileHandle <> 0 then
  begin
    LSpeicher := MapViewOfFile(fFileHandle, FILE_MAP_WRITE, 0, 0, 0);
    setlength(LDest, length(LSpeicher));
    StrCopy(PChar(LDest), LSpeicher);
    UnmapViewOfFile(LSpeicher);
    result := LDest;
    CloseHandle(fFileHandle);
  end;
end;
Eine Demo dazu hat SirThornberry hier angehängt.



Suchworte: IPC MMF

[edit=Chakotay1308]Beitrag klassifiziert. Mfg, Chakotay1308[/edit]
[edit=Matze]Die Anmerkung von Cyberstorm, UnmapViewOfFile() aufzurufen, ergänzt. MfG, Matze[/edit]
  Mit Zitat antworten Zitat