Delphi-PRAXiS
Seite 2 von 5     12 34     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Log-Datei realisieren (https://www.delphipraxis.net/103023-log-datei-realisieren.html)

Reinhard Kern 9. Nov 2007 00:41

Re: Log-Datei realisieren
 
Zitat:

Zitat von Infect
Hallo allerseits,

ich möchte gerne eine Log-Datei realisieren, in die mehrere Programme (bzw. mehrere Instanzen desselben Programms) ihre Einträge machen. Wie realisiere ich so etwas am besten, ohne dass die Programme sich beim Hineinschreiben in die Datei in die Quere kommen?

Bisher hatte ich folgende Routine vorgesehen für das Anhängen von Log-Einträgen:
Delphi-Quellcode:
AssignFile(f, 'C:\Test.log');
try
  Append(f);
  Writeln(f, 'Ein Log-Eintrag');
finally
  CloseFile(f);
end;
Hier kann es aber theoretisch passieren, dass zwei Programme gleichzeitig die Datei öffnen wollen und dann kracht es bei dem Programm, das einen Tick später drangekommen ist.

Hallo,

warum versuchst du nicht das Eingachste: die Logdatei exklusiv zu öffen. Das kann immer nur ein Programm, ein anderes muss es später nochmal versuchen.

Gruss Reinhard

himitsu 9. Nov 2007 01:36

Re: Log-Datei realisieren
 
ohne Stream gehts genauso ... einfach versuchen die Datei exklusiv zu öffnen
Delphi-Quellcode:
AssignFile(F, LogFile);
FileMode := fmOpenReadWrite or fmShareExclusive;
{$I-}
Append(F);
WriteLn(F, S);
If IOResult <> 0 Then <<ging nich>>;
CloseFile(F);
{$I+}
tja und wenn's nich geht, dann halt 'ne Weile versuchen
Delphi-Quellcode:
AssignFile(F, LogFile);
FileMode := fmOpenReadWrite or fmShareExclusive;
Try
  Repeat
    {$I-} Append(F); {$I+}
    Sleep(10);
  Until IOResult = 0;
  WriteLn(F, S);
Finally
  CloseFile(F);
End;
soooo, und jetzt noch 'ne Zeitbegrenzung und so'n Zeugs rein ... fertsch (denk'sch ma)
Delphi-Quellcode:
Function AddLog(Const LogFile, S: String; TimeOut{ms}: LongWord = 3000): Boolean;
  Var F: TextFile;
    C: LongWord;
    M: Byte;

  Begin
    Result  := False;
    M       := FileMode;
    FileMode := fmOpenReadWrite or fmShareExclusive;
    AssignFile(F, LogFile);
    Try
      C := GetTickCount;
      While True do Begin
        {$I-} Append(F); {$I+}
        If IOResult = 0 Then Break;
        If GetTickCount - C > TimeOut Then Exit;
        //Application.ProcessMessages;
        Sleep(10);
      End;
      WriteLn(F, S);
      Result := True;
    Finally
      CloseFile(F);
      FileMode := M;
    End;
  End;

If not AddLog('a.log', 'irgendwas muß rein') Then Error...
OK, als WinAPI sieht's och nett aus ^^
Delphi-Quellcode:
Function AddLog(LogFile, S: String; TimeOut{ms}: LongWord = 3000): Boolean;
  Var H: THandle;
    C: LongWord;

  Begin
    Result := False;
    S     := S + #13#10;
    C     := GetTickCount;
    Repeat
      H := CreateFile(PChar(LogFile), GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0);
      If H <> INVALID_HANDLE_VALUE Then Begin
        SetFilePointer(H, 0, nil, FILE_END);
        WriteFile(H, S[1], Length(S), C, nil);
        CloseHandle(H);
        Result := True;
        Exit;
      End;
      //Application.ProcessMessages;
      Sleep(10);
    Until GetTickCount - C > TimeOut;
  End;
[add]
ich sollt vielleicht ma weniger nebenbai chatten ... da is doch plötlich 'nen neuer Beitrag drin und sogar mit RedBox ^^

[edit]
immer diese Rechtschreibfehler :wall:

Andreas H. 9. Nov 2007 05:29

Re: Log-Datei realisieren
 
Hallo,

nur so aus der Hüfte geschossen...

wenn das exklusive Öffnen nix is, dann vielleicht nen kleinen Server aufsetzen, in dem per POST oder so die Logmeldungen gesendet werden. Ist natürlich aufwendiger, als "nur" ne Prozedur zu schreiben. Dann wäre auch das Dateiformat und der Speicherort gekapselt.

Vielleicht läuft ja schon ein Apache oÄ. And ein paar Zeilen PHP...

Aber wenn denn schon von verschiedenen Programmen auf verschiedenen Rechnern Logmeldungen zentral gesichert werden sollen...

Gruß Andreas

peschai 9. Nov 2007 05:40

Re: Log-Datei realisieren
 
Hallo
ich hätte auch noch eine grundsätzliche idee:
Parallele schreibzugriffe schreiben in temporäre weitere neue log's, welche beim nächsten schreibzugang wieder zusammengeführt werden. Die weiteren templogs', welche es nur gab, weil das Hauptlog gesperrt war, leben nur so lange, wie der nächste schreibzugriff erfolgt. Wer also das Hauptlog exclusiv öffnen kann, muss zuerst die anderen templogs auslesen und reinschreiben, dann diese templogs löschen und dann erst seine eigenen Sachen eintragen ...

was meint ihr ?

peschai 9. Nov 2007 05:44

Re: Log-Datei realisieren
 
Noch etwas zum EventLog des Betriebssystem. Das ist eigentlich fürs betriebssystem nahe Applikationen. Wenn da jeder seinen Müll reinwirft, dann hat es ein Admi wirklich schwer...
Tip das Eventlog für eigene Programme NICHT verwenden! Besser eine Logdatei abgelegt unter "Einstellungen und Dokumente" ...
:???:

mkinzler 9. Nov 2007 06:38

Re: Log-Datei realisieren
 
Der trend geht aber zum Eventlog, welcher i9n Vista deshalb stark erweitert wurde.

marabu 9. Nov 2007 06:58

Re: Log-Datei realisieren
 
Hallo Leute,

ein logfile soll ja für einen bestimmten Zeitraum ein lückenloses Protokoll der Aktionen oder Ereignisse im Leben eines Programms liefern. Wenn das Protokoll wichtig ist, dann muss es lokal geschrieben werden, da bei einer instabilen Netzwerkverbindung ein Entscheidungsproblem entsteht: Muss der Client jetzt seine Arbeit einstellen. In einem Client-Server-Scenario lässt man den Server protokollieren. Schreiben die Clients eigene lokale Protokolle, dann ist eine übergreifende Auswertung durch Zusammenführen der logfiles möglich, auch wenn ich mir die Notwendigkeit gerade nicht vorstellen kann.

Grüße vom marabu

MatthiasR 9. Nov 2007 10:28

Re: Log-Datei realisieren
 
Erstmal Danke für die vielen Vorschläge! Ich habe mir nun anhand von himitsus Beispielen noch etwas selbst zusammengebaut. Bitte schaut euch das mal an, was es daran auszusetzen gibt. Zuvor aber noch ein paar für mich offene Fragen:
  • Was bewirkt die Compiler-Direktive {$I}? Ist die nur dazu da, dass bei Append keine Exception ausgelöst wird, wenn die Datei schon offen ist? Könnte man die Direktive also auch weglassen und stattdessen mit Exceptions arbeiten (wie ich in meinem Beispiel)?
  • Was bewirkt die Zeile "FileMode := fmOpenReadWrite or fmShareExclusive;" genau? Ich habe mir dazu mal bissle die Hilfe durchgelesen, aber so richtig schlau wurde ich nicht daraus.
  • Müsste das finale "CloseFile" nicht auch wieder mit der Direktive {$I} geklammert werden, zumindest bei mir kommt ein "E/A-Fehler 103", wenn ich "CloseFile" aufrufe und die Datei war zuvor nicht mit "Append" geöffnet worden. Oder man führt einfach ein weiteres Flag ein, wie in meiner Lösung, ob das Öffnen zuvor geklappt hat.

Hier mein Entwurf:
Delphi-Quellcode:
procedure TForm1.btnWriteLnClick(Sender: TObject);
var
  s: String;
  FFile: TextFile;
  bSuccess: Boolean;
  iBeginTime: Integer;
  iWaitTime: Integer;
begin
  bSuccess := False;
  iBeginTime := GetTickCount;
  iWaitTime := 0;
  AssignFile(FFile, 'C:\Test.log');
  try
    while (iWaitTime < 10000) do
    begin
      try
        Append(FFile);
        if (ParamCount > 0) then
          s := 'Programm ' + ParamStr(1)
        else
          s := 'Programm 1';
        WriteLn(FFile, s);
        bSuccess := True;
        Break;
      except
        Sleep(10);
        iWaitTime := getTickCount - iBeginTime;
      end;
    end;

    if (not bSuccess) then
      ShowMessage('Schreiben fehlgeschlagen.')
    else
      ShowMessage('Schreiben erfolgreich.')
  finally
    if bSuccess then
      CloseFile(FFile);
  end;
end;

shmia 9. Nov 2007 13:59

Re: Log-Datei realisieren
 
Zitat:

Zitat von Infect
Ich habe mir nun anhand von himitsus Beispielen noch etwas selbst zusammengebaut.

Ich verstehe nicht, weshalb du eine Bastel-Lösung gegenüber einer Profilösung bevorzugst ? :?
Delphi-Quellcode:
var
  logstream: TExclusiveFileStream;
  s : string;
begin
  logstream := TExclusiveFileStream.Create('C:\Test.log', 10000);
  try
    logstream.SeektoEnd; // Ans Dateiende, wir wollen anhängen
    if (ParamCount > 0) then
      s := 'Programm ' + ParamStr(1)
    else
      s := 'Programm 1';    
    s := s + #13#10; // Zeilenvorschub
    logstream.WriteBuffer(s[1], length(s)); // Daten schreiben
  finally
    logstream.Free;
  end;
end;

Reinhard Kern 9. Nov 2007 14:11

Re: Log-Datei realisieren
 
Zitat:

Zitat von Infect
Erstmal Danke für die vielen Vorschläge! Ich habe mir nun anhand von himitsus Beispielen noch etwas selbst zusammengebaut. Bitte schaut euch das mal an, was es daran auszusetzen gibt. Zuvor aber noch ein paar für mich offene Fragen:
  • Was bewirkt die Zeile "FileMode := fmOpenReadWrite or fmShareExclusive;" genau? Ich habe mir dazu mal bissle die Hilfe durchgelesen, aber so richtig schlau wurde ich nicht daraus.

Hallo,

dadurch, dass du das einfach weglässt, ist dein Entwurf reiner Unsinn. Du hast weder meinen noch den Beitrag himitsus auch nur annähernd verstanden. Vielleicht solltest du mal ganz einfach anfangen "watt is eine Datei"...

Gruss Reinhard


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:06 Uhr.
Seite 2 von 5     12 34     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz