Autor |
Beitrag |
woully
      
Beiträge: 78
|
Verfasst: Mo 06.07.09 11: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 20:26
Wie ist TExchangeData definiert? Die müssen bei Sender und Empfänger identisch sein.
|
|
woully 
      
Beiträge: 78
|
Verfasst: Di 07.07.09 09: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 10: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 11: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 11: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 12: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 12: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 13:21, insgesamt 3-mal bearbeitet
|
|
woully 
      
Beiträge: 78
|
Verfasst: Di 07.07.09 13: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 13: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 13: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 13: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 15: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 15: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 16: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 16:26
Vielleicht verwendest Du in beiden Programmen verschiedene Variablen (globale, lokale, nicht initialisierte usw.)
|
|
woully 
      
Beiträge: 78
|
Verfasst: Di 07.07.09 16: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 17: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 19: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 09: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 ???

|
|
|