Entwickler-Ecke
Dateizugriff - Filesharing zwischen C++ und Delphi
MisterCP - Mi 29.09.10 10:43
Titel: Filesharing zwischen C++ und Delphi
Hallo,
ich hoffe hier jemanden u finden, der sich sowohl mit C als auch mit Delphi auskennt.
Folgende Konstellation von Programmen führt bei mir zu einem Problem
Anwendung A: C-Programm, schreibt zyklisch Daten in eine Datei
Anwendung B: C-Programm vom gleichen Programmierer, liest Daten aus der oben geschriebenen Datei von Anwendung A ohne das es zu irgendeiner Zeit Probleme beim schreibenden Zugriff gibt
Anwendung C: Delphi-Programm (das ist meins), erzeugt in Anwendung A Probleme beim schreiben.
Ich habe auf meiner (Delphi-)Seite folgenden Code verwendet:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| try //File öffnen if FileExists(FileName) = true then begin hFile := TFileStream.Create(FileName, fmOpenRead, fmShareDenyNone) //keine Beschränkung des Zugriffs //hFile := TFileStream.Create(FileName, fmOpenRead, fmShareDenyRead) //andere Applikationen haben Schreibrecht, //aber kein Leserecht //hFile := TFileStream.Create(FileName, fmOpenRead, fmShareCompat) //Sharing is compatible with the way FCBs are opened end{erster if-Zweig} else begin result := eCantOpenFile; end;{if} except //Fehlerbehandlung result := eCantOpenFile; end;{try..except} |
Egal welche form der Zugriffsbeschränkung ich verwende, Anwendung A behauptet, nicht mehr in den File schreiben zu dürfen (geht erst wieder, wenn ich ihn geschlossen habe)
Frage: kann ich auf meiner (Delphi-)Seite noch irgendetwas anders parametrieren, damit Anwendung A weiterhin schreiben kann?
Ich weiß leider nicht was Anwendung A an Berechtigungen abfragt, da ich von diesem Programm keine Source habe, aber da Anwendung B das gleiche macht wie ich und es da zu keinen Kollisionen kommt muß es ja irgend eine Form des Sharings bei C geben, die ich event. auch unter Delphi aufrufen kann.
Ich bedanke mich jetzt schon für eure konstuktiven Vorschläge ganz herzlich.
ch. Peterson
jaenicke - Mi 29.09.10 10:56
Hallo und :welcome:
Schau einfach mit dem Process Monitor nach wie auf die Dateien zugegriffen wird.
Flamefire - Mi 29.09.10 12:21
Oder mit Ollydbg (o.ä.) den Aufruf von Program B auf FileOpen kontrollieren.
Was ich aber für wahrscheinlicher halte: Programm A & B verwenden eine Semaphor zur Synchronisierung. D.h. Es hat GENAU 1 Programm Zugriffsrechte.
Delete - Mi 29.09.10 14:57
Hier ist ein funktionierendes Beispiel - CORETEMP ist in C++ programmiert und schreibt OHNE Probleme Daten
in das SHARED MEMORY.
Ausgelesen werden die Daten 1 oder 2x/sec von dem DELPHI-Programm.
ReadCTInfo wird NUR beim Programmstart aufgerufen, danach müssen die Daten nur noch timergesteuert ausgelesen werden,
denn das 'CoreTempMappingObject' bleibt bis zum Programmende erhalten.
http://www.delphi-forum.de/viewtopic.php?t=83627&highlight=coretemp
MisterCP - Mi 29.09.10 15:54
Erst mal vielen Dank für die schnellen Antworten.
@hathor: Deine Antwort macht mir Angst :-) Ich bin leider kein Profi und das sieht unheimlich kompliziert aus.
Ich hatte eher an eine Fehlerursache in der Definition des Funktionsaufrufs gedacht, so in der Art, daß Delphi irgend eine API anders interpretiert als das C-Programm (MFC).
Das liegt aus dem Grunde nahe, da mir jemand ein Beispielprogramm in C geschrieben hat, was eben nur die Datei öffnet und offen hält und Programm A kann munter weiter rein schreiben.
Ich kann nur leider nicht mein ganzes Projekt nach C portieren, da ich C nicht mal richtig lesen geschweige denn schreiben kann.
Kann man die Klasse TFilestream auch direkt nochmal aus irgend einer Windows-Dll einbinden? (und macht das Sinn?)
Flamefire - Mi 29.09.10 19:03
Dann zeig dochmal dein C Programm, was funktioniert...
jaenicke - Mi 29.09.10 19:32
MisterCP hat folgendes geschrieben : |
Kann man die Klasse TFilestream auch direkt nochmal aus irgend einer Windows-Dll einbinden? (und macht das Sinn?) |
Die Klasse ist ein Wrapper um die API-Funktionen. Zum Beispiel um CreateFile um die Datei zu öffnen bzw. zu erstellen.
Aber was soll denn das ganze Herumgerate? Nimm doch einfach wie ich schon sagte den Process Monitor, dann siehst du in 5 Minuten was Sache ist... :roll:
MisterCP - Mi 29.09.10 20:36
Die Lösung ist gefunden !!!
Die schlechte Nachricht ist, das müßte theoretisch tausende User betreffen, die mit Delphi 5.0 arbeiten
Es handelt sich anscheinend tatsächlich um einen Fehler in der Unit "Classes"
Im Construktor wurde meiner Meinung nach beim
Quelltext
1:
| inherited Create(FileOpen(FileName, Mode)); |
das "or Rights" vergessen. Ich meine es sollte so aussehen:
Quelltext
1:
| inherited Create(FileOpen(FileName, Mode or Rights)); |
Um aber da nicht dauerhaft dran rumzufuschen, (falls es das doch nicht war) hab ich mir die Klasse "TFileStreamC" mal zusammenkopiert.
Zumindest klappt es nun mit dem gemeinsamen Zugriff auf die Datei.
Trotzdem bleibt die Frage: Hat Delphi wirklich solche Fehler?
Trotzdem noch mal vielen Dank und schönen Abend noch.
jaenicke - Mi 29.09.10 21:20
MisterCP hat folgendes geschrieben : |
das "or Rights" vergessen. Ich meine es sollte so aussehen:
Quelltext 1:
| inherited Create(FileOpen(FileName, Mode or Rights)); | |
Die Rechte spielen beim Öffnen der Datei keine Rolle, deshalb ist das schon richtig so.
Wenn eine Datei erzeugt wird, müssen die Rechte aber gesetzt werden, also bei FileCreate.
Und jetzt sehe ich auch deinen Fehler... So ist es richtig:
Delphi-Quelltext
1:
| hFile := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone) |
Du hast da ein Komma gesetzt...
MisterCP - Mi 29.09.10 22:46
nun, daß ICH einen fehler gemacht hätte war ja auch meine Vermutung, aber die Schnittstelle zum Construktor in der "Classes" lauet ja:
Quelltext
1:
| constructor TFileStream.Create(const FileName: string; Mode: Word; Rights: Cardinal); |
Blieb mir also gar nichts anderes übrig, als das Komma zu setzen, oder?
Nur eben, das innerhalb des Construktors die Rights dann nicht verarbeitet wurden.
Und wenn mich nicht alles täuscht hatte ich das Filehandling auch bei Herrn Doberenz abgeschrieben (wobei Abschreiben ja keine Tippfehler ausschließt)
Was ich da jetzt aber nicht verstehe ist
Zitat: |
Die Rechte spielen beim Öffnen der Datei keine Rolle, deshalb ist das schon richtig so.
Wenn eine Datei erzeugt wird, müssen die Rechte aber gesetzt werden, also bei FileCreate.
|
Erzeugen tut die Datei ja Anwendung A und A schließt sie dann wieder und öffnet, schreibt was neues und schließt...
Und wenn dann jemand anderes mit drauf zugreift sollte man schon schauen, ob man grad zugreifen darf oder lieber nicht.
Nur eben, daß mein Delphi-Programm beim öffnen nicht mitgeteilt hat, das es ihm egal ist ob noch jemand anderes gleichzeitig schreibt.
jaenicke - Mi 29.09.10 23:38
Das sind keine Rechte, das sind alles Zugriffsmodi und gehören daher verodert in den entsprechenden Parameter.
Rechte regeln die Zugriffsrechte eines Benutzers auf eine Datei. Die Modi, die du meinst, regeln den parallelen Zugriff, sind aber keine Rechte.
Flamefire - Do 30.09.10 12:09
Hast du dir mal den ganzen Construktor angeguckt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| if Mode = fmCreate then begin inherited Create(FileCreate(AFileName, Rights)); if FHandle = INVALID_HANDLE_VALUE then raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(AFileName), SysErrorMessage(GetLastError)]); end else begin inherited Create(FileOpen(AFileName, Mode)); if FHandle = INVALID_HANDLE_VALUE then raise EFOpenError.CreateResFmt(@SFOpenErrorEx, [ExpandFileName(AFileName), SysErrorMessage(GetLastError)]); end; |
Die Rechte werden beim Erstellen verwendet (Datei existiert potenziell nicht, bzw wird neu erstellt), die Modi beim öffnen einer vorhandenen Datei.
Und: Die Rechte bei windows sind eh egal, weil ignoriert:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function FileCreate(const FileName: string; Rights: Integer): Integer; {$IFDEF MSWINDOWS} begin Result := FileCreate(FileName); end; {$ENDIF} {$IFDEF LINUX} begin Result := Integer(open(PChar(FileName), O_RDWR or O_CREAT or O_TRUNC, Rights)); end; {$ENDIF} |
Martok - Do 30.09.10 18:26
Flamefire hat folgendes geschrieben : |
Und: Die Rechte bei windows sind eh egal, weil ignoriert:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function FileCreate(const FileName: string; Rights: Integer): Integer; {$IFDEF MSWINDOWS} begin Result := FileCreate(FileName); end; {$ENDIF} {$IFDEF LINUX} begin Result := Integer(open(PChar(FileName), O_RDWR or O_CREAT or O_TRUNC, Rights)); end; {$ENDIF} | |
Aber nur, weil Delphi da mal wieder nur die Hälfte wrappt.
Mit anderen Worten: Borland hat beim File-IO maximal verkackt. Was sie schreiben wollten, wäre wohl eher sowas anstatt separater Open/Create-Funktionen:
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:
| function FOpen(FileName: string; Mode: LongWord): Integer; const AccessMode: array[0..2] of LongWord = ( GENERIC_READ, GENERIC_WRITE, GENERIC_READ or GENERIC_WRITE); ShareMode: array[0..4] of LongWord = ( 0, 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE); OpenMode: Cardinal; begin Result := -1; if Mode and fmCreate>0 then OpenMode:= CREATE_ALWAYS else OpenMode:= OPEN_EXISTING; if ((Mode and 3) <= fmOpenReadWrite) and ((Mode and $F0) <= fmShareDenyNone) then Result := Integer(CreateFile(PChar(FileName), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4], nil, OpenMode, FILE_ATTRIBUTE_NORMAL, 0)); end; |
Wenn du statt TFileStream THandleStream nutzt, kannst du ja das Handle direkt selber übergeben.
BenBE - Fr 01.10.10 12:00
@Martok: Bei Signed-Typen sollte man bei Bitoperationen auf <> 0 prüfen. Auch wenn das hier ftaucht. Ganz davon abgsehen, dass JZ/JNZ weniger Aufwand für die CPU als ein JG/JNLE macht.
Und für die Create-File-Anweisung war wohl auch kein Platz mehr da?
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!