diff --git a/src/Agent/AutopilotMonitor.Agent.Core/Monitoring/MonitoringService.cs b/src/Agent/AutopilotMonitor.Agent.Core/Monitoring/MonitoringService.cs
index 69553477..45fa6108 100644
--- a/src/Agent/AutopilotMonitor.Agent.Core/Monitoring/MonitoringService.cs
+++ b/src/Agent/AutopilotMonitor.Agent.Core/Monitoring/MonitoringService.cs
@@ -403,12 +403,20 @@ namespace AutopilotMonitor.Agent.Core.Monitoring
}
// Check for enrollment completion events
- if (_configuration.SelfDestructOnComplete &&
- (evt.EventType == "enrollment_complete" || evt.EventType == "enrollment_failed"))
+ if (evt.EventType == "enrollment_complete" || evt.EventType == "enrollment_failed")
{
_logger.Info($"Enrollment completion detected: {evt.EventType}");
- Task.Run(() => HandleEnrollmentComplete());
- return; // Don't continue with normal event processing
+
+ // ALWAYS delete session ID when enrollment is complete/failed
+ // This ensures a new session will be created on next enrollment
+ DeleteSessionId();
+
+ // Only trigger self-destruct if configured
+ if (_configuration.SelfDestructOnComplete)
+ {
+ Task.Run(() => HandleEnrollmentComplete());
+ return; // Don't continue with normal event processing
+ }
}
// Immediate upload for:
@@ -499,6 +507,26 @@ namespace AutopilotMonitor.Agent.Core.Monitoring
}
}
+ ///
+ /// Deletes the persisted session ID file
+ /// Should be called when enrollment is complete/failed
+ ///
+ private void DeleteSessionId()
+ {
+ _logger.Info("Deleting persisted session ID...");
+ try
+ {
+ var dataDirectory = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor");
+ var sessionPersistence = new SessionPersistence(dataDirectory);
+ sessionPersistence.DeleteSession();
+ _logger.Info("Session ID deleted successfully");
+ }
+ catch (Exception ex)
+ {
+ _logger.Warning($"Failed to delete session ID: {ex.Message}");
+ }
+ }
+
///
/// Handles enrollment completion and triggers self-destruct sequence
///
@@ -520,7 +548,7 @@ namespace AutopilotMonitor.Agent.Core.Monitoring
// Give a moment for final upload to complete
await Task.Delay(2000);
- // Step 3: Execute self-destruct
+ // Step 3: Execute self-destruct or cleanup
if (_configuration.SelfDestructOnComplete)
{
ExecuteSelfDestruct();
diff --git a/src/Agent/AutopilotMonitor.Agent.Core/Storage/SessionPersistence.cs b/src/Agent/AutopilotMonitor.Agent.Core/Storage/SessionPersistence.cs
new file mode 100644
index 00000000..4f4361bc
--- /dev/null
+++ b/src/Agent/AutopilotMonitor.Agent.Core/Storage/SessionPersistence.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+
+namespace AutopilotMonitor.Agent.Core.Storage
+{
+ ///
+ /// Manages persistent session ID storage to maintain tracking across agent restarts
+ ///
+ public class SessionPersistence
+ {
+ private readonly string _sessionFilePath;
+ private readonly object _lockObject = new object();
+
+ public SessionPersistence(string dataDirectory)
+ {
+ if (string.IsNullOrWhiteSpace(dataDirectory))
+ {
+ throw new ArgumentNullException(nameof(dataDirectory));
+ }
+
+ if (!Directory.Exists(dataDirectory))
+ {
+ Directory.CreateDirectory(dataDirectory);
+ }
+
+ _sessionFilePath = Path.Combine(dataDirectory, "session.id");
+ }
+
+ ///
+ /// Loads existing session ID from disk or creates a new one if none exists
+ ///
+ /// Session ID (GUID string)
+ public string LoadOrCreateSessionId()
+ {
+ lock (_lockObject)
+ {
+ try
+ {
+ // Check if session file exists and is valid
+ if (File.Exists(_sessionFilePath))
+ {
+ var sessionId = File.ReadAllText(_sessionFilePath).Trim();
+
+ // Validate it's a valid GUID format
+ if (Guid.TryParse(sessionId, out _))
+ {
+ return sessionId;
+ }
+ }
+
+ // Create new session ID if file doesn't exist or is invalid
+ var newSessionId = Guid.NewGuid().ToString();
+ File.WriteAllText(_sessionFilePath, newSessionId);
+ return newSessionId;
+ }
+ catch (Exception ex)
+ {
+ // If we can't read/write the session file, generate a new ID in memory
+ // Log this error if logger is available
+ throw new InvalidOperationException($"Failed to load or create session ID at {_sessionFilePath}", ex);
+ }
+ }
+ }
+
+ ///
+ /// Deletes the persisted session ID file
+ /// This should be called when enrollment is complete
+ ///
+ public void DeleteSession()
+ {
+ lock (_lockObject)
+ {
+ try
+ {
+ if (File.Exists(_sessionFilePath))
+ {
+ File.Delete(_sessionFilePath);
+ }
+ }
+ catch (Exception)
+ {
+ // Suppress deletion errors - not critical if cleanup fails
+ // The file will be overwritten on next start anyway
+ }
+ }
+ }
+
+ ///
+ /// Checks if a persisted session ID exists
+ ///
+ /// True if session file exists
+ public bool SessionExists()
+ {
+ lock (_lockObject)
+ {
+ return File.Exists(_sessionFilePath);
+ }
+ }
+ }
+}
diff --git a/src/Agent/AutopilotMonitor.Agent/AutopilotMonitorService.cs b/src/Agent/AutopilotMonitor.Agent/AutopilotMonitorService.cs
index 7a9aca97..0fbc1f0e 100644
--- a/src/Agent/AutopilotMonitor.Agent/AutopilotMonitorService.cs
+++ b/src/Agent/AutopilotMonitor.Agent/AutopilotMonitorService.cs
@@ -3,6 +3,7 @@ using System.ServiceProcess;
using AutopilotMonitor.Agent.Core.Configuration;
using AutopilotMonitor.Agent.Core.Logging;
using AutopilotMonitor.Agent.Core.Monitoring;
+using AutopilotMonitor.Agent.Core.Storage;
namespace AutopilotMonitor.Agent
{
@@ -61,12 +62,15 @@ namespace AutopilotMonitor.Agent
private AgentConfiguration LoadConfiguration()
{
- // TODO: Load from registry or config file
- // For now, return a default configuration
+ // Load or create persisted session ID
+ var dataDirectory = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor");
+ var sessionPersistence = new SessionPersistence(dataDirectory);
+ var sessionId = sessionPersistence.LoadOrCreateSessionId();
+
return new AgentConfiguration
{
ApiBaseUrl = Environment.GetEnvironmentVariable("AUTOPILOT_MONITOR_API") ?? "http://localhost:7071",
- SessionId = Guid.NewGuid().ToString(),
+ SessionId = sessionId,
TenantId = "default-tenant",
SpoolDirectory = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor\Spool"),
LogDirectory = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor\Logs"),
diff --git a/src/Agent/AutopilotMonitor.Agent/Program.cs b/src/Agent/AutopilotMonitor.Agent/Program.cs
index 5a3a82f8..3a1536f4 100644
--- a/src/Agent/AutopilotMonitor.Agent/Program.cs
+++ b/src/Agent/AutopilotMonitor.Agent/Program.cs
@@ -6,6 +6,7 @@ using System.ServiceProcess;
using AutopilotMonitor.Agent.Core.Configuration;
using AutopilotMonitor.Agent.Core.Logging;
using AutopilotMonitor.Agent.Core.Monitoring;
+using AutopilotMonitor.Agent.Core.Storage;
using Microsoft.Win32;
using Newtonsoft.Json;
@@ -264,10 +265,20 @@ namespace AutopilotMonitor.Agent
}
}
+ // Load or create persisted session ID
+ var dataDirectory = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor");
+ var sessionPersistence = new SessionPersistence(dataDirectory);
+ var sessionId = sessionPersistence.LoadOrCreateSessionId();
+
+ var sessionStatus = sessionPersistence.SessionExists() && File.GetCreationTime(Path.Combine(dataDirectory, "session.id")) < DateTime.Now.AddMinutes(-1)
+ ? "Restored from previous session"
+ : "New session created";
+ Console.WriteLine($"Session ID: {sessionId} ({sessionStatus})");
+
return new AgentConfiguration
{
ApiBaseUrl = apiBaseUrl,
- SessionId = Guid.NewGuid().ToString(),
+ SessionId = sessionId,
TenantId = tenantId,
SpoolDirectory = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor\Spool"),
LogDirectory = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor\Logs"),