using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace InstallMonitor { public class LogReader { private CancellationTokenSource _cts; private ConfigService _configService; private long _lastPosition = 0; private int _retryCount = 0; public LogReader(ConfigService config, CancellationTokenSource cts) { _configService = config; _cts = cts; } public string Directory => _configService.Settings.LogFileDirectory; public string FilePattern => _configService.Settings.LogFileNamePattern; public int MaxRetries => _configService.Settings.MaxRetries; public int RetryTimeout => _configService.Settings.RetryTimeout; public string LogFile { get; private set; } = string.Empty; public event EventHandler? InternalError; public event EventHandler? ReadLine; public event EventHandler? StreamOpen; public event EventHandler? AwaitLine; public event EventHandler? TaskFailed; private void FindLogFile() { var file = new DirectoryInfo(Directory) .GetFiles(FilePattern) .OrderByDescending(f => f.Name) .FirstOrDefault(); if (file != null) { LogFile = file.FullName; } if (!File.Exists(LogFile)) throw new IOException("Datei nicht gefunden"); } public async Task ReadLogAsync() { while (!_cts.Token.IsCancellationRequested) { try { FindLogFile(); using var fs = new FileStream(LogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using var reader = new StreamReader(fs, System.Text.Encoding.UTF8, true); StreamOpened(); if (_lastPosition == 0) { string? line; while ((line = await reader.ReadLineAsync()) != null) { LineRead(line); } _lastPosition = fs.Position; } while (!_cts.IsCancellationRequested) { fs.Seek(_lastPosition, SeekOrigin.Begin); string? line; while ((line = await reader.ReadLineAsync()) != null) { LineRead(line); } _lastPosition = fs.Position; await Task.Delay(200, _cts.Token); LineAwaited(); } } catch (OperationCanceledException ex) { } catch (Exception ex) when (_retryCount < MaxRetries) { InternalErrorCaught($"Versuch: ({_retryCount + 1}/{MaxRetries}) - {ex.Message}"); _retryCount++; await Task.Delay(RetryTimeout, _cts.Token); } catch (Exception ex) { TaskHasFailed($"Versuch: (no more retries) - {ex.Message}"); break; } } } public void StreamOpened() { _retryCount = 0; var handle = StreamOpen; if(handle != null) handle.Invoke(null, EventArgs.Empty); } public void LineRead(string line) { var handle = ReadLine; if (handle != null) handle.Invoke(line, EventArgs.Empty); } public void LineAwaited() { var handle = AwaitLine; if (handle != null) handle.Invoke(null, EventArgs.Empty); } public void InternalErrorCaught(string message) { var handle = InternalError; if (handle != null) handle.Invoke(message, EventArgs.Empty); } public void TaskHasFailed(string message) { var handle = InternalError; if (handle != null) handle.Invoke(message, EventArgs.Empty); } } }