| 
| Autor | Beitrag |  
| woully 
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Mo 06.07.09 10:18 
 
Hi,
 ich hätte da mal ein problem.
 Ich habe einen Service entwickelt der Daten mit einer Zweiten Software austauschen soll. Dazu verwende ich die Memory mapped files.
 Meine erzeugen, lesen und schreib Funktionen von der Mappfile funktionnieren ganz gut. Der Datenaustauch zwischen 2 Software funtionniert Problemlos. Sobald aber ein Service mit einer Software Daten austauchen soll gibt es Problemen. Alle Funktionen werden Fehlerlos ausgeführt, aber die Datenwerte die mir der Service zurückgibt stimmen nicht mit den Daten die von der Zweiten Software geschrieben werden über ein....
 Kann mir jemand helfen ?
 Hier mal der Code von der MMF.
 			Moderiert von									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 
 | function TMemoryMappedFile.CreateMMF : Boolean;Begin
 Result := False;
 try
 aMMFHandle := CreateFileMapping($FFFFFFFF, nil,PAGE_READWRITE, 0, sizeOf(TExchangeData), Pchar('MedavisFileMapping'));
 if aMMFHandle = 0 then
 raise Exception.Create('CreateFileMapping-Error!');
 finally
 end;
 Result := True;
 end;
 
 Function TMemoryMappedFile.WriteToMMF(pData : pExchangeData) : Boolean;
 Begin
 Result := False;
 try
 aMMFHandle := OpenFileMapping(FILE_MAP_WRITE,False,pchar('MedavisFileMapping'));
 if aMMFHandle = 0 then
 exit;
 pViewData := MapViewOfFile(aMMFHandle, FILE_MAP_WRITE,0, 0, 0);
 CopyMemory(pViewData,pdata,SizeOf(texchangeData));
 finally
 end;
 Result := True;
 end;
 
 Function TMemoryMappedFile.ReadFromMMF(var pData : pExchangeData) : boolean;
 begin
 Result := False;
 try
 aMMFHandle := OpenFileMapping(FILE_MAP_READ,False,pchar('MedavisFileMapping'));
 if aMMFHandle = 0 then
 exit;
 
 pViewData := MapViewOfFile(aMMFHandle, FILE_MAP_READ, 0, 0, 0);
 CopyMemory(pData,pViewdata,SizeOf(texchangeData));
 finally
 end
 end;
 |   Narses: Delphi-Tags hinzugefügt
Moderiert von  Narses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt. |  |  |  
| hathor Ehemaliges Mitglied
 Erhaltene Danke: 1
 
 
 
 
 | 
Verfasst: Mo 06.07.09 19:26 
 
Wie ist TExchangeData definiert? Die müssen bei Sender und Empfänger identisch sein. |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Di 07.07.09 08:02 
 
Hi,
 TexchangeData habe ich in einer Unit definiert die beim Empfänger und beim Sender eingebunden ist.
 Also identisch.
 
 Wie schon erwähnt, muss das Problem irgendwie mit dem Service zusammenhängen, da der Datenaustausch mit einem Tform sender, und TForm empfänger funktionniert...
 |  |  |  
| hathor Ehemaliges Mitglied
 Erhaltene Danke: 1
 
 
 
 
 | 
Verfasst: Di 07.07.09 09:47 
 
Sicherheitshalber mal nachgefragt:
 1. die beiden Programme nutzen den gleichen physikalischen RAM ?
 2. das "CreateFileMapping" wird nur von einer Seite (Sender) durchgeführt?
 Wenn ja, dann teste doch mal meinen Code:
 												| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 51:
 52:
 53:
 54:
 55:
 56:
 57:
 58:
 59:
 60:
 61:
 62:
 63:
 64:
 65:
 66:
 67:
 68:
 69:
 70:
 71:
 72:
 73:
 74:
 75:
 76:
 77:
 78:
 79:
 80:
 81:
 82:
 83:
 84:
 85:
 86:
 87:
 88:
 89:
 90:
 91:
 92:
 93:
 94:
 95:
 96:
 97:
 98:
 99:
 100:
 101:
 102:
 103:
 104:
 105:
 106:
 107:
 108:
 109:
 110:
 111:
 112:
 113:
 114:
 115:
 116:
 117:
 118:
 119:
 120:
 121:
 122:
 123:
 124:
 125:
 126:
 127:
 128:
 129:
 130:
 131:
 132:
 133:
 134:
 135:
 136:
 137:
 138:
 139:
 140:
 141:
 142:
 143:
 144:
 145:
 
 | unit Unit1;
 interface
 
 uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls;
 
 Type
 TExchangeData = record
 sName : array [0..99] of Char;
 sTime : String[100];
 end;
 
 PExchangeData = ^TExchangeData;
 pViewData = ^TExchangeData;
 
 type
 TForm1 = class(TForm)
 Label1: TLabel;
 Timer1: TTimer;
 cb_Timer: TCheckBox;
 CREATE1: TButton;
 Create2: TCheckBox;
 Write2: TCheckBox;
 Read2: TCheckBox;
 CREATE3: TLabel;
 WRITE1: TButton;
 READ1: TButton;
 WRITE3: TLabel;
 READ3: TLabel;
 READ4: TLabel;
 procedure FormCreate(Sender: TObject);
 procedure cb_TimerClick(Sender: TObject);
 procedure CREATE1Click(Sender: TObject);
 procedure WRITE1Click(Sender: TObject);
 procedure READ1Click(Sender: TObject);
 procedure Timer1Timer(Sender: TObject);
 
 private
 
 public
 
 end;
 
 var
 Form1: TForm1;
 ExchangeData : PExchangeData;
 ViewData  : pViewData;
 implementation
 
 {$R *.dfm}
 
 
 procedure TForm1.cb_TimerClick(Sender: TObject);
 begin
 if cb_Timer.Checked  then TIMER1.Enabled:=true else TIMER1.enabled:=false;
 end;
 
 procedure TForm1.FormCreate(Sender: TObject);
 begin     Label1.caption:='TEST';
 end;
 
 procedure TForm1.Timer1Timer(Sender: TObject);
 begin
 WRITE2.Checked:=false;
 READ2.Checked:=false;
 Label1.Caption:= DateTimeToStr(now);Timer1.Tag:= Timer1.Tag +1;
 if Timer1.Tag=1 then WRITE1Click(self);
 if Timer1.Tag=2 then
 BEGIN
 READ1Click(self);
 Timer1.Tag:=0;
 END;
 end;
 
 function CreateMMF : Boolean;
 var aMMFHandle : Integer;
 Begin
 Result := False;
 try
 aMMFHandle :=
 CreateFileMapping($FFFFFFFF, nil,PAGE_READWRITE, 0, sizeOf(TExchangeData),
 Pchar('MedavisFileMapping'));
 if aMMFHandle = 0 then
 raise Exception.Create('CreateFileMapping-Error!');
 finally
 end;
 Result := True;
 end;
 
 function ReadInfo : Boolean;
 var myHandle : Integer;
 begin
 myHandle :=  OpenFileMapping(FILE_MAP_READ, False, 'MedavisFileMapping');
 if myHandle > 0 then
 begin
 ExchangeData := MapViewOfFile(myHandle, FILE_MAP_READ, 0, 0, 0);
 Result := True;
 end else result := false;
 CloseHandle(myHandle);
 end;
 
 procedure TForm1.CREATE1Click(Sender: TObject);
 begin
 CREATE2.checked:= CreateMMF; CREATE3.caption:='CREATE';
 end;
 
 procedure TForm1.WRITE1Click(Sender: TObject); var myHandle : Integer;
 begin
 WRITE2.checked:=false;
 myHandle :=  OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MedavisFileMapping');
 if myHandle > 0 then
 BEGIN
 ExchangeData := MapViewOfFile(myHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
 
 with ExchangeData^ do
 BEGIN
 sName:= 'OK';
 sTime:= DateTimeToStr(now);
 END;
 
 CloseHandle(myHandle);
 WRITE3.Caption:='OK'; WRITE2.checked:=true;
 END;
 end;
 
 
 procedure TForm1.READ1Click(Sender: TObject);
 begin    READ2.checked:=true;
 READ3.caption:= ExchangeData.sName;
 READ4.caption:= ExchangeData.sTime;
 end;
 
 end.
 | 
Einloggen, um Attachments anzusehen!
 |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Di 07.07.09 10:45 
 
humm, 
 dein code funktionniert auch.
 
 Das mit dem RAM... Kann ich irgendwie nachvollziehen wo sich windows die Datei ablegt ?.
 Vermutlich arbeitet eine TService Klasse anderst als die TForm..
 |  |  |  
| hathor Ehemaliges Mitglied
 Erhaltene Danke: 1
 
 
 
 
 | 
Verfasst: Di 07.07.09 10:56 
 
	  |  woully hat folgendes geschrieben  : |  	  | humm, 
 dein code funktionniert auch.
 
 Das mit dem RAM... Kann ich irgendwie nachvollziehen wo sich windows die Datei ablegt ?.
 Vermutlich arbeitet eine TService Klasse anderst als die TForm..
 | 
 Ich wollte mit meiner Frage nach dem RAM nur sicher gehen, dass das RAM in EINEM PC genutzt wird und nicht in ZWEI VERSCHIEDENEN! Ausserdem darf "CreateFileMapping" nur 1 mal ausgeführt werden. |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Di 07.07.09 11:07 
 
  ok, also da kannst du beruhigt sein. Beide programme laufen auf dem gleichen PC...
 Ich habe mal einen Schreib und Lese Zugriff aus meinem Service getestet. Da funktioniert es.
 pfff... keinen Schimer mehr wo das Problem liegen könnte...   |  |  |  
| ffgorcky 
          Beiträge: 573
 
 WIN XP/2000 & 7Prof (Familie:Win95,Win98)
 
 
 | 
Verfasst: Di 07.07.09 11:55 
 
Also entschuldigung, falls ich damit das ganze auf "unsaubere Abwege" bringe, aber ich fände es wesentlich einfacher, das ganze in einer Datei zwischenzuspeichern, so das das andere Programm (z.B. timer-gesteuert) immer nur nachguckt, ob eine neue Datei-Nachricht für ihn da ist - z.B. mit:
 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 4:
 
 | uses DateUtils; 
 var LetzterDateiaustausch:TDateTime;
 FilePfadUndName:String
 |  		                       Delphi-Quelltext 
 									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 
 | procedure TFormWieAuchImmerDuSieNennst.OnCreate(Sender: TObject);begin
 FileName:='WieAuchImmerDuDieDateiNennstEvtlMitPfadVorausWennSieNichtImSelbenVerzeichnisStehenDarf.Endung'
 end;
 
 
 procedure TFormWieAuchImmerDuSieNennst.TimerDateiaustauschOnTimer(Sender: TObject);
 var VergangeneZeit:
 begin
 if FileExists(FilePfadUndName) then
 begin
 VergangeneZeit:=now-LetzterDateiaustausch;
 HoursRemaining:=Trunc(VergangeneZeit * 24);
 MinutesRemaining:=Trunc((VergangeneZeit*24-HoursRemaining)*60);
 SecondsRemaining:=Trunc(((VergangeneZeit*24-HoursRemaining)*60-MinutesRemaining)*60);
 Edit1.Text:=Format('%d:%d:%d',[HoursRemaining,MinutesRemaining,SecondsRemaining]);
 
 FileDate := FileAge(FileName);
 DateTime := FileDateToDateTime(FileDate);
 if SecondsBetween(LetzterDateiaustausch, DateTime) > 30 then
 begin
 FileClose(filecreate(FileName));
 if deletefile(FileName)
 LetzterDateiaustausch:=DateTime;
 end;
 end;
 end;
 |  Wobei ich das jetzt ja nur von diesem  und diesem Beitrag  ohne Kontrolle (weil ich hier leider gerade keine Entwicklungsumgebeung habe!) abgewandelt habe und ich habe auf dem Gebiet sonst auch noch nich so wirklich viele Erfahrungen...
 ...und ich muss jetzt leider abrupt aufhören, da ich jetzt einen anderen Termin habe...   *grmpf* 
 Zuletzt bearbeitet von ffgorcky am Di 07.07.09 12:21, insgesamt 3-mal bearbeitet
 |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Di 07.07.09 12:18 
 
hummm stimmt, 
 wäre nä möglichkeit...
 
 Trotzdem würde ich gerne die lösung es über filemapping zu machen.
 |  |  |  
| hathor Ehemaliges Mitglied
 Erhaltene Danke: 1
 
 
 
 
 | 
Verfasst: Di 07.07.09 12:23 
 
Dann nimm doch mal meinen Code und DEIN TExchangeData, um zu sehen, ob die Daten schon da verstümmelt werden.
 z.B. durch zuwenig oder unterschiedliche Speicherreservierung, andere Reihenfolge bei der Definition...
 Was noch wichtig ist:
 		                       Delphi-Quelltext 
 									| 1:2:
 
 |    sName : array [0..99] of Char;    sTime : String[100]; 					 |  |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Di 07.07.09 12:42 
 
Hi,
 hatte bei dem Test mit deinem Quellcode schon getestet.
 
 Könnte es irgend etwas mit zugriffsberechtigung zu tun haben, wenn die Mapped Datei aus einem Windows dienst angesprochen wird ?
 |  |  |  
| BenBE 
          Beiträge: 8721
 Erhaltene Danke: 191
 
 Win95, Win98SE, Win2K, WinXP
 D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
 
 | 
Verfasst: Di 07.07.09 12:42 
 
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
 |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Di 07.07.09 14:38 
 
DupHandle ?
 muss ich zugeben das ich jetzt überfordert bin.. ich habe zwar eineiges auf internet gefunde, aber nichts was mit Mapping files zu tun hat..
 
 Haäätest du ein kleines Beispiel ?
 
 danke
 |  |  |  
| BenBE 
          Beiträge: 8721
 Erhaltene Danke: 191
 
 Win95, Win98SE, Win2K, WinXP
 D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
 
 | 
Verfasst: Di 07.07.09 14:43 
 
Du duplizierst mit DuplicateHandle einfach das Access Token für die MMF und schenkst eine Kopie davon dem Zielprozess.
 Alternativ könntest Du das MMF auch auf eine reale Datei abbilden, statt das ganze rein im RAM zu halten.
 
 Schau auch einmal, ob du dein MMF sauber flushst (zum Speichern der Änderungen), da das AFAIR nicht automatisch zwischen den Prozessen transparent gemappt wird.
 _________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
 |  |  |  
| Xentar 
          Beiträge: 2077
 Erhaltene Danke: 2
 
 Win XP
 Delphi 5 Ent., Delphi 2007 Prof
 
 | 
Verfasst: Di 07.07.09 15:14 
 
Wäre es nicht auch möglich, dass du einen Fehler in deiner Lese-Prozedur, und nicht im MMF selber hast? _________________ PROGRAMMER: A device for converting coffee into software.
 |  |  |  
| hathor Ehemaliges Mitglied
 Erhaltene Danke: 1
 
 
 
 
 | 
Verfasst: Di 07.07.09 15:26 
 
Vielleicht verwendest Du in beiden Programmen verschiedene Variablen (globale, lokale, nicht initialisierte usw.) |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Di 07.07.09 15:27 
 
Hallo Xentar,
 nein. Ich habe die Schreib und Lese funktionen getestet, indem ich mit Zwei Programme auf die MMF zugegriffen habe.
 Sobald ich aber mit einem Dienst auf die MMF zugreife funktionniert es nicht.
 
 Ich glaube schon das BenBE mich auf den richtigen Weg gebracht hat.
 Ich teste mal das DuplicateHandle und gebe euch dann das Ergebnis.
 |  |  |  
| hathor Ehemaliges Mitglied
 Erhaltene Danke: 1
 
 
 
 
 | 
Verfasst: Di 07.07.09 16:06 
 
Return Value
 If the function succeeds, the return value is the starting address of the mapped view.
 
 If the function fails, the return value is NULL. To get extended error information, call GetLastError.
 
 Lass Dir doch mal return value anzeigen.
 |  |  |  
| MSCH 
          Beiträge: 1448
 Erhaltene Danke: 3
 
 W7 64
 XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
 
 | 
Verfasst: Di 07.07.09 18:31 
 
Lass doch mal dein Service unter einen User-Account (dengleichen den die anwendung verwendet) laufen.
Was passiert da?
 :-msch
 _________________ ist das politisch, wenn ich linksdrehenden Joghurt haben möchte?
 |  |  |  
| woully  
          Beiträge: 78
 
 
 
 
 | 
Verfasst: Mi 08.07.09 08:38 
 
Hi,
 so jetzt bin ich kurz vor dem kündigen..
 Ich habe soweit alles getestet, versucht, quellcode nachgeprüft...
 Rückgabewerte sind i.O., Pointer adressen stimmen.
 Dieser sche*** funktioniert nicht.    Ich habe mal meine Memory Mapping funktionen in eine DLL eingefügt, und einen pointer als Shared ausgegeben. 
 Das funktionniert auch nicht...
 Jemand noch nä idee ???
   |  |  |  |