Autor Beitrag
MisterCP
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mi 29.09.10 10:43 
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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 29.09.10 10:56 
Hallo und :welcome:

Schau einfach mit dem Process Monitor nach wie auf die Dateien zugegriffen wird.

Für diesen Beitrag haben gedankt: BenBE
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: 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.

Für diesen Beitrag haben gedankt: BenBE
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: 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.

www.delphi-forum.de/...p;highlight=coretemp

Für diesen Beitrag haben gedankt: BenBE
MisterCP Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Mi 29.09.10 19:03 
Dann zeig dochmal dein C Programm, was funktioniert...
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 29.09.10 19:32 
user profile iconMisterCP hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: 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

ausblenden Quelltext
1:
inherited Create(FileOpen(FileName, Mode));					


das "or Rights" vergessen. Ich meine es sollte so aussehen:

ausblenden 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.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 29.09.10 20:55 
Dann versuch mal die Nutzung von THandleStream, statt TFilestream. Wie die Werte im Constructor sein müssen, weißt Du ja jetzt ;-)

Ggf. auch anhand der Compiler-Version abfragen (Omorphia.version.inc dürfte Dir dabei helfen), ob Du das über nen TFilestream oder über nen THandleStream machst.

_________________
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.

Für diesen Beitrag haben gedankt: jaenicke
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 29.09.10 21:20 
user profile iconMisterCP hat folgendes geschrieben Zum zitierten Posting springen:
das "or Rights" vergessen. Ich meine es sollte so aussehen:

ausblenden 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:
ausblenden Delphi-Quelltext
1:
hFile := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone)					
Du hast da ein Komma gesetzt...

Für diesen Beitrag haben gedankt: BenBE
MisterCP Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.

Für diesen Beitrag haben gedankt: BenBE
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Do 30.09.10 12:09 
Hast du dir mal den ganzen Construktor angeguckt:
ausblenden 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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Do 30.09.10 18:26 
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Und: Die Rechte bei windows sind eh egal, weil ignoriert:
ausblenden 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:

ausblenden 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..2of LongWord = (
    GENERIC_READ,
    GENERIC_WRITE,
    GENERIC_READ or GENERIC_WRITE);
  ShareMode: array[0..4of 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 $F0shr 4], nil, OpenMode,
      FILE_ATTRIBUTE_NORMAL, 0));
end;


Wenn du statt TFileStream THandleStream nutzt, kannst du ja das Handle direkt selber übergeben.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."

Für diesen Beitrag haben gedankt: BenBE
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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?

_________________
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.