| 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.
 																	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;					 				 | 			 		 	  
Moderiert von  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 ???
    
 
 | 
 
 |  
 
 
 |