InstallMonitor/InstallMonitor/LogReader.cs
2025-09-29 10:09:35 +02:00

142 lines
4.4 KiB
C#

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);
}
}
}