mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
simplified bootstrapper script and introduced --install parameter for agent
This commit is contained in:
@@ -37,16 +37,11 @@ param(
|
||||
# Configuration - Everything in ProgramData for easy cleanup
|
||||
$AgentBasePath = "$env:ProgramData\AutopilotMonitor"
|
||||
$AgentBinPath = "$AgentBasePath\Agent"
|
||||
$AgentSpoolPath = "$AgentBasePath\Spool"
|
||||
$AgentLogsPath = "$AgentBasePath\Logs"
|
||||
$TaskName = "AutopilotMonitor-Agent"
|
||||
$LogFile = "$AgentLogsPath\Bootstrap.log"
|
||||
$LogFile = "$AgentBasePath\Bootstrap.log"
|
||||
|
||||
# Ensure directories exist
|
||||
New-Item -Path $AgentBasePath -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
New-Item -Path $AgentBinPath -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
New-Item -Path $AgentSpoolPath -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
New-Item -Path $AgentLogsPath -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message)
|
||||
@@ -213,54 +208,18 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
# Register as Scheduled Task (survives reboots, easy to remove)
|
||||
Write-Log "Registering Scheduled Task..."
|
||||
|
||||
# Check if task already exists
|
||||
$existingTask = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
|
||||
|
||||
if ($null -ne $existingTask) {
|
||||
Write-Log "Scheduled Task already exists - removing old task"
|
||||
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
|
||||
# Let the agent install/deploy itself and manage its own Scheduled Task
|
||||
Write-Log "Calling agent install mode (--install)..."
|
||||
& $agentExePath --install
|
||||
$installExitCode = $LASTEXITCODE
|
||||
if ($installExitCode -ne 0) {
|
||||
throw "Agent install failed with exit code $installExitCode"
|
||||
}
|
||||
|
||||
# Create action - run agent executable
|
||||
$action = New-ScheduledTaskAction -Execute $agentExePath -WorkingDirectory $AgentBinPath
|
||||
|
||||
# Create trigger - run at computer startup
|
||||
$trigger = New-ScheduledTaskTrigger -AtStartup
|
||||
|
||||
# Create settings - run whether user is logged on or not
|
||||
$settings = New-ScheduledTaskSettingsSet `
|
||||
-AllowStartIfOnBatteries `
|
||||
-DontStopIfGoingOnBatteries `
|
||||
-StartWhenAvailable `
|
||||
-RunOnlyIfNetworkAvailable `
|
||||
-ExecutionTimeLimit (New-TimeSpan -Hours 0) # No time limit
|
||||
|
||||
# Create principal - run as SYSTEM
|
||||
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
|
||||
|
||||
# Register the task
|
||||
Register-ScheduledTask `
|
||||
-TaskName $TaskName `
|
||||
-Action $action `
|
||||
-Trigger $trigger `
|
||||
-Settings $settings `
|
||||
-Principal $principal `
|
||||
-Description "Autopilot Monitor Agent - Temporary enrollment monitoring" `
|
||||
-Force
|
||||
|
||||
Write-Log "Scheduled Task registered successfully"
|
||||
|
||||
# Start the task immediately (don't wait for next reboot)
|
||||
Write-Log "Starting agent task..."
|
||||
Start-ScheduledTask -TaskName $TaskName
|
||||
Write-Log "Agent task started"
|
||||
Write-Log "Agent install mode completed successfully"
|
||||
|
||||
Write-Log "===== Bootstrap Completed Successfully ====="
|
||||
Write-Log "Agent Path: $AgentBasePath"
|
||||
Write-Log "Scheduled Task: $TaskName"
|
||||
Write-Log "Scheduled Task: managed by agent (--install)"
|
||||
Write-Log "Agent will monitor enrollment and auto-remove when complete"
|
||||
Write-Log "Bootstrap log: $LogFile"
|
||||
Write-Log ""
|
||||
|
||||
@@ -15,6 +15,13 @@ namespace AutopilotMonitor.Agent
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// Install mode: ensure folders, deploy payload, create/update Scheduled Task, and start it.
|
||||
if (args.Contains("--install"))
|
||||
{
|
||||
RunInstallMode(args);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for mass rollout simulator mode
|
||||
if (args.Contains("--simulator-mass-rollout"))
|
||||
{
|
||||
@@ -28,6 +35,86 @@ namespace AutopilotMonitor.Agent
|
||||
RunAgent(args);
|
||||
}
|
||||
|
||||
static void RunInstallMode(string[] args)
|
||||
{
|
||||
var logDir = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor\Logs");
|
||||
var logger = new AgentLogger(logDir, enableDebug: true);
|
||||
var consoleMode = args.Contains("--console") || Environment.UserInteractive;
|
||||
|
||||
try
|
||||
{
|
||||
logger.Info("======================= Agent install mode (--install) =======================");
|
||||
|
||||
EnsureAgentDirectories(logger);
|
||||
|
||||
var sourceExePath = Assembly.GetExecutingAssembly().Location;
|
||||
var sourceDir = Path.GetDirectoryName(sourceExePath) ?? string.Empty;
|
||||
var targetAgentDir = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor\Agent");
|
||||
var targetExePath = Path.Combine(targetAgentDir, "AutopilotMonitor.Agent.exe");
|
||||
|
||||
if (!string.Equals(
|
||||
Path.GetFullPath(sourceDir).TrimEnd('\\'),
|
||||
Path.GetFullPath(targetAgentDir).TrimEnd('\\'),
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.Info($"Install mode called from '{sourceDir}'. Deploying payload to '{targetAgentDir}'.");
|
||||
CopyDirectory(sourceDir, targetAgentDir, logger);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Info("Agent already running from target install directory; payload copy not required.");
|
||||
}
|
||||
|
||||
var taskName = "AutopilotMonitor-Agent";
|
||||
var taskCommand = $"\"{targetExePath}\"";
|
||||
|
||||
logger.Info($"Registering Scheduled Task '{taskName}' for executable: {targetExePath}");
|
||||
|
||||
var createExitCode = RunProcess(
|
||||
"schtasks.exe",
|
||||
$"/Create /TN \"{taskName}\" /TR \"{taskCommand}\" /SC ONSTART /RU SYSTEM /RL HIGHEST /F",
|
||||
logger);
|
||||
|
||||
if (createExitCode != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to create/update Scheduled Task '{taskName}' (exit code {createExitCode})");
|
||||
}
|
||||
|
||||
logger.Info($"Scheduled Task '{taskName}' created/updated successfully");
|
||||
|
||||
var startExitCode = RunProcess(
|
||||
"schtasks.exe",
|
||||
$"/Run /TN \"{taskName}\"",
|
||||
logger);
|
||||
|
||||
if (startExitCode != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to start Scheduled Task '{taskName}' (exit code {startExitCode})");
|
||||
}
|
||||
|
||||
logger.Info($"Scheduled Task '{taskName}' started successfully");
|
||||
|
||||
if (consoleMode)
|
||||
{
|
||||
Console.WriteLine("Installation completed successfully.");
|
||||
Console.WriteLine($"Task: {taskName}");
|
||||
Console.WriteLine($"Executable: {targetExePath}");
|
||||
Console.WriteLine($"Log: {logDir}");
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error("Registration mode failed", ex);
|
||||
if (consoleMode)
|
||||
{
|
||||
Console.WriteLine($"ERROR: {ex.Message}");
|
||||
}
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void RunAgent(string[] args)
|
||||
{
|
||||
var consoleMode = args.Contains("--console") || Environment.UserInteractive;
|
||||
@@ -416,6 +503,103 @@ namespace AutopilotMonitor.Agent
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void EnsureAgentDirectories(AgentLogger logger)
|
||||
{
|
||||
var basePath = Environment.ExpandEnvironmentVariables(@"%ProgramData%\AutopilotMonitor");
|
||||
var paths = new[]
|
||||
{
|
||||
basePath,
|
||||
Path.Combine(basePath, "Agent"),
|
||||
Path.Combine(basePath, "Spool"),
|
||||
Path.Combine(basePath, "Logs")
|
||||
};
|
||||
|
||||
foreach (var path in paths)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
logger.Info($"Created directory: {path}");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Debug($"Directory already exists: {path}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int RunProcess(string fileName, string arguments, AgentLogger logger)
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
logger.Info($"Executing: {fileName} {arguments}");
|
||||
|
||||
using (var process = Process.Start(psi))
|
||||
{
|
||||
if (process == null)
|
||||
throw new InvalidOperationException($"Failed to start process: {fileName}");
|
||||
|
||||
var stdout = process.StandardOutput.ReadToEnd();
|
||||
var stderr = process.StandardError.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(stdout))
|
||||
logger.Info($"Process output: {stdout.Trim()}");
|
||||
if (!string.IsNullOrWhiteSpace(stderr))
|
||||
logger.Warning($"Process error output: {stderr.Trim()}");
|
||||
|
||||
logger.Info($"Process exit code: {process.ExitCode}");
|
||||
return process.ExitCode;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CopyDirectory(string sourceDir, string targetDir, AgentLogger logger)
|
||||
{
|
||||
if (!Directory.Exists(sourceDir))
|
||||
throw new DirectoryNotFoundException($"Source directory not found: {sourceDir}");
|
||||
|
||||
Directory.CreateDirectory(targetDir);
|
||||
|
||||
foreach (var dir in Directory.GetDirectories(sourceDir, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
var rel = dir.Substring(sourceDir.Length).TrimStart('\\');
|
||||
Directory.CreateDirectory(Path.Combine(targetDir, rel));
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
var rel = file.Substring(sourceDir.Length).TrimStart('\\');
|
||||
var dest = Path.Combine(targetDir, rel);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(dest) ?? targetDir);
|
||||
|
||||
try
|
||||
{
|
||||
File.Copy(file, dest, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// If destination exists, keep going and let scheduled task use the latest available payload.
|
||||
if (File.Exists(dest))
|
||||
{
|
||||
logger.Warning($"Could not overwrite '{dest}': {ex.Message}. Keeping existing file.");
|
||||
continue;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info($"Payload deployment completed: '{sourceDir}' -> '{targetDir}'");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if another AutopilotMonitor.Agent.exe process is already running.
|
||||
/// </summary>
|
||||
|
||||
@@ -1 +1 @@
|
||||
9
|
||||
12
|
||||
|
||||
Reference in New Issue
Block a user