163 lines
5.4 KiB
C#
163 lines
5.4 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Text;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Threading;
|
|
using LANCommander.Packager.Models;
|
|
using LANCommander.Packager.Services;
|
|
|
|
namespace LANCommander.Packager.Views;
|
|
|
|
public partial class MonitoringView : UserControl
|
|
{
|
|
private readonly PackageContext _context;
|
|
private readonly StringBuilder _logText = new();
|
|
private readonly ConcurrentQueue<string> _pendingLogEntries = new();
|
|
private InstallerMonitorService? _monitorService;
|
|
private DispatcherTimer? _updateTimer;
|
|
private volatile int _lastFileCount;
|
|
private volatile int _lastRegistryCount;
|
|
private volatile bool _installerExited;
|
|
private string _detectedInstallDirectory = string.Empty;
|
|
|
|
public event Action? MonitoringCompleted;
|
|
|
|
public MonitoringView(PackageContext context)
|
|
{
|
|
_context = context;
|
|
InitializeComponent();
|
|
}
|
|
|
|
public void StartMonitoring()
|
|
{
|
|
_monitorService = new InstallerMonitorService();
|
|
|
|
_monitorService.OnFileChange += entry =>
|
|
{
|
|
_lastFileCount = _monitorService.FileChangeCount;
|
|
};
|
|
|
|
_monitorService.OnRegistryChange += entry =>
|
|
{
|
|
_lastRegistryCount = _monitorService.RegistryChangeCount;
|
|
};
|
|
|
|
_monitorService.OnInstallerExited += () =>
|
|
{
|
|
_installerExited = true;
|
|
_pendingLogEntries.Enqueue("Installer exited.");
|
|
};
|
|
|
|
_updateTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
|
|
_updateTimer.Tick += (_, _) => FlushUpdates();
|
|
_updateTimer.Start();
|
|
|
|
StatusLabel.Text = "Preparing...";
|
|
|
|
var logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "packager.log");
|
|
|
|
File.WriteAllText(logPath, $"=== Packager started {DateTime.Now} ==={Environment.NewLine}");
|
|
|
|
Task.Run(() =>
|
|
{
|
|
try
|
|
{
|
|
Action<string> log = msg =>
|
|
{
|
|
try
|
|
{
|
|
File.AppendAllText(logPath, msg + Environment.NewLine);
|
|
}
|
|
catch { }
|
|
|
|
_pendingLogEntries.Enqueue(msg);
|
|
};
|
|
|
|
var mode = _monitorService.LaunchInstaller(_context.InstallerPath, log);
|
|
|
|
Dispatcher.UIThread.Post(() =>
|
|
{
|
|
StatusLabel.Text = mode == "snapshot"
|
|
? "Installer running (snapshot mode). Waiting..."
|
|
: "Installer running (Interposer). Monitoring...";
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Dispatcher.UIThread.Post(() =>
|
|
{
|
|
StatusLabel.Text = "Error - see packager.log";
|
|
|
|
_pendingLogEntries.Enqueue($"Exception: [{ex.GetType().Name}] {ex.Message}");
|
|
_pendingLogEntries.Enqueue($"Installer: {_context.InstallerPath}");
|
|
|
|
if (ex.InnerException != null)
|
|
_pendingLogEntries.Enqueue($"Inner: {ex.InnerException.Message}");
|
|
|
|
_pendingLogEntries.Enqueue(ex.StackTrace ?? "");
|
|
|
|
try
|
|
{
|
|
File.AppendAllLines(logPath, new[]
|
|
{
|
|
$"Exception: [{ex.GetType().Name}] {ex.Message}",
|
|
ex.StackTrace ?? ""
|
|
});
|
|
}
|
|
catch { }
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
private void FlushUpdates()
|
|
{
|
|
FileCountLabel.Text = $"Files changed: {_lastFileCount}";
|
|
RegistryCountLabel.Text = $"Registry entries: {_lastRegistryCount}";
|
|
|
|
bool hasNew = false;
|
|
|
|
while (_pendingLogEntries.TryDequeue(out var entry))
|
|
{
|
|
_logText.AppendLine(entry);
|
|
hasNew = true;
|
|
}
|
|
|
|
if (hasNew)
|
|
{
|
|
EventLog.Text = _logText.ToString();
|
|
EventLog.CaretIndex = EventLog.Text.Length;
|
|
}
|
|
|
|
if (_installerExited)
|
|
{
|
|
_installerExited = false;
|
|
_updateTimer?.Stop();
|
|
|
|
// Detect install directory before disposing the monitor service
|
|
if (_monitorService != null)
|
|
_detectedInstallDirectory = _monitorService.DetectInstallDirectory();
|
|
|
|
// Dispose the monitor service to stop all background Interposer activity
|
|
_context.FileChanges = _monitorService?.FileChanges.ToList() ?? [];
|
|
_context.RegistryChanges = _monitorService?.RegistryChanges.ToList() ?? [];
|
|
_monitorService?.Dispose();
|
|
_monitorService = null;
|
|
|
|
// Final drain
|
|
while (_pendingLogEntries.TryDequeue(out var remaining))
|
|
_logText.AppendLine(remaining);
|
|
|
|
EventLog.Text = _logText.ToString();
|
|
EventLog.CaretIndex = EventLog.Text.Length;
|
|
|
|
FileCountLabel.Text = $"Files changed: {_lastFileCount}";
|
|
RegistryCountLabel.Text = $"Registry entries: {_lastRegistryCount}";
|
|
StatusLabel.Text = "Done! Press Next to continue.";
|
|
|
|
MonitoringCompleted?.Invoke();
|
|
}
|
|
}
|
|
|
|
public InstallerMonitorService? GetMonitorService() => _monitorService;
|
|
public string GetDetectedInstallDirectory() => _detectedInstallDirectory;
|
|
}
|