Search code examples
filedelphitimerwindows-servicesfilereader

Delphi: Timer in Service Stops my FileReader


I am writing a Service that has a Timer which should check every 60 seconds if a Line has a particular number. Here is the code of the timer:

procedure TConnectionChecker.Timer2Timer(Sender: TObject);
var
  myFile: TextFile;
  sLine: string;
  fileOpenLog: TStreamWriter;
  fileOpenLogName, fileOpenLogPathName: string;

begin
  ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
  filename:= 'restult.txt';
  filePath:= TPath.Combine(exePath, 'OutputFile');
  filePathName:= TPath.Combine(filePath, filename);
  fileOpenLogName:= 'Log_fileOpen.txt';
  serviceLogPath:= TPath.Combine(exePath, 'LogFiles');
  fileOpenLogPathName:= TPath.Combine(serviceLogPath, fileOpenLogName);
  fileOpenLog := TStreamWriter.Create(TFileStream.Create(fileOpenLogPathName, fmCreate or fmShareDenyWrite));

  if not FileExists(filePathName) then
  begin
    fileOpenLog.WriteLine('File not found');
    TServiceThread.Current.Terminate;
    fileOpenLog.Free;
  end;
  fileOpenLog.WriteLine('File found');
  try
    AssignFile(myFile, filePathName);
    Reset(myFile);
    fileOpenLog.WriteLine('File opened');

    while NOT eof(myFile) do
    begin
      PingWorkedAufrufe:= PingWorkedAufrufe + 1;
      readln(myFile, sLine);
      fileOpenLog.WriteLine('Read Line: ' + sLine);
      checkIfPingWorked(sLine);
    end;
    fileOpenLog.WriteLine('EOF');

  finally
    CloseFile(myFile);
  end;
  fileOpenLog.Free;
end;

And here is the code of my Procedure: checkIfPingWorked:

procedure TConnectionChecker.checkIfPingWorked(ALine: String);
var
  AValue, StartOfLineToFind: String;
  checkIfPingWorkedLog: TStreamWriter;
  checkIfPingWorkedLogName, checkIfPingWorkedLogPathName: string;
begin
  ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));

  StartOfLineToFind:= '    Pakete: Gesendet =';
  ip:= '...';
  fileName:= 'restult.txt';
  filepath:= TPath.Combine(exePath, 'OutputFile');
  filepathname:= TPath.Combine(filepath, fileName);
  serviceLogPath:= TPath.Combine(exePath, 'LogFiles');
  checkIfPingWorkedLogName:= 'Log_checkIfPingWorked.txt';

  checkIfPingWorkedLogPathName := TPath.Combine(serviceLogPath, checkIfPingWorkedLogName);
  checkIfPingWorkedLog := TStreamWriter.Create(TFileStream.Create(checkIfPingWorkedLogPathName, fmCreate or fmShareDenyWrite));
  checkIfPingWorkedLog.WriteLine('Zeilen werden überprüft');
  if Pos(StartOfLineToFind, ALine) = 1 then
  begin
    AValue:= Copy(ALine, 39, 1);
    if AValue = IntToStr(5) then
      checkIfPingWorkedLog.WriteLine('Success')
    else
    begin
      checkIfPingWorkedLog.WriteLine('Error');

      //Writing E-Mail...
      //Authentifizierung
      IdSMTP1.AuthType := TIdSMTPAuthenticationType.satDefault;

      //Benutzerdaten für Authentifizierung
      IdSMTP1.Username := '...';
      IdSMTP1.Password := '...';

      //Server-Daten
      IdSMTP1.Host := '...';
      IdSMTP1.Port := ...;

      IdSMTP1.Connect;

      try
        IdMessage1.From.Address := '';
        IdMessage1.Recipients.EMailAddresses := '';
        //IdMessage1.CCList.EMailAddresses := '';
        //IdMessage1.BCCList.EMailAddresses := '';
        IdMessage1.Subject := '--AUTOMATISCHE BENACHRICHTIGUNG--';
        IdMessage1.Body.Text := 'Der PC mit der IP: ' + ip + ' konnte nicht mehr erreicht werden';
        IdSMTP1.Send(IdMessage1);
      finally
        IdSMTP1.Disconnect;
      end;
      checkIfPingWorkedLog.WriteLine('Email sent');
      TServiceThread.Current.Terminate;
    end;
  end;
  checkIfPingWorkedLog.Free;
end;

But I can only read the first two lines and then it stops.

Important to say is that I originally wrote this as a normal Program. And it worked fine. Now I am converting it into a Windows Service.


Solution

  • The Problem was, that I created everywhere and everytime new Log Files. Now I Create one Log file on Service Create:

    procedure TConnectionChecker.ServiceCreate(Sender: TObject);
    var
      logFilePathName, logFileName, exePath, logFilePath: String;
    begin
       ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
       logFileName:= 'log_connectionTest.txt';
       logFilePath:= TPath.Combine(exePath, 'logFile');
       logFilePathName:= TPath.Combine(logFilePath, logFileName);
    
       if not TDirectory.Exists(logFilePath) then
        TDirectory.CreateDirectory(logFilePath);
    
       swLogFile:= TStreamWriter.Create(TFileStream.Create(logFilePathName, fmCreate or fmShareDenyWrite));
    end;
    

    And I made a procedure where I ask for 2 params (destination and text) and write the line to the Log file.:

    procedure TConnectionChecker.WriteToLog(destination, Text: string);
    begin
      swLogFile.WriteLine('[' + DateTimeToStr(now) + '] ' + destination + ' schreibt: ' + text);
    end;
    

    Finally I can call it in every procedure:

     WriteToLog('checkIfPingWorked', 'Success')