- downloadSetup() nutzte process.env.AGENT_VERSION statt der Patch-Gruppen- Zielversion → Staged Rollout (Test/Pilot/Produktion) hatte nie funktioniert, jeder Agent bekam beim Auto-Update immer dieselbe globale Version - Fix: downloadSetup() löst jetzt per ?hostname=X die Gruppen-Zielversion auf, exakt wie checkin() es bereits tat - ApiService.DownloadSetupAsync() schickt jetzt den Hostnamen mit - Version: 2.4.0 → 2.5.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
152 lines
5.5 KiB
C#
152 lines
5.5 KiB
C#
using ITNexusAgent.Models;
|
|
using System.Diagnostics;
|
|
using System.Management;
|
|
using System.Net.Http;
|
|
|
|
namespace ITNexusAgent.Services;
|
|
|
|
public class CommandExecutor(ApiService api, string hostname, string dataDir, string exePath)
|
|
{
|
|
private readonly ApiService _api = api;
|
|
private readonly string _hostname = hostname;
|
|
private readonly string _dataDir = dataDir;
|
|
private readonly string _exePath = exePath;
|
|
|
|
private static void RunSchtasks(string args) =>
|
|
Process.Start(new ProcessStartInfo("schtasks.exe", args) { CreateNoWindow = true })?.WaitForExit();
|
|
|
|
public async Task ExecuteAsync(PatchCommand cmd)
|
|
{
|
|
string result;
|
|
try
|
|
{
|
|
result = cmd.Command switch
|
|
{
|
|
"check_updates" => await CheckUpdates(),
|
|
"install_updates" => await InstallUpdates(),
|
|
"reboot" => await Reboot(cmd.Id),
|
|
"upgrade_win11" => await UpgradeWin11(),
|
|
"update_agent" => await UpdateAgent(),
|
|
"shell_exec" => await ShellExec(cmd.Params ?? ""),
|
|
_ => $"Unbekannter Command: {cmd.Command}"
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result = $"Fehler: {ex.Message}";
|
|
}
|
|
|
|
if (cmd.Command != "reboot")
|
|
{
|
|
await _api.ReportCommandResultAsync(new CommandResult
|
|
{
|
|
CommandId = cmd.Id,
|
|
Status = "done",
|
|
Result = result
|
|
});
|
|
}
|
|
}
|
|
|
|
private Task<string> CheckUpdates()
|
|
{
|
|
Process.Start(new ProcessStartInfo("UsoClient.exe", "StartScan") { CreateNoWindow = true });
|
|
Thread.Sleep(5000);
|
|
return Task.FromResult("Update-Scan gestartet");
|
|
}
|
|
|
|
private Task<string> InstallUpdates()
|
|
{
|
|
Process.Start(new ProcessStartInfo("UsoClient.exe", "StartDownload") { CreateNoWindow = true });
|
|
Thread.Sleep(3000);
|
|
Process.Start(new ProcessStartInfo("UsoClient.exe", "StartInstall") { CreateNoWindow = true });
|
|
return Task.FromResult("Update-Installation gestartet");
|
|
}
|
|
|
|
private async Task<string> Reboot(int cmdId)
|
|
{
|
|
await _api.ReportCommandResultAsync(new CommandResult
|
|
{
|
|
CommandId = cmdId,
|
|
Status = "done",
|
|
Result = "Neustart wird in 60 Sekunden durchgeführt"
|
|
});
|
|
Process.Start("shutdown.exe", "/r /t 60 /c \"IT Nexus Patch Management - Geplanter Neustart\"");
|
|
return "";
|
|
}
|
|
|
|
private Task<string> UpgradeWin11()
|
|
{
|
|
var exePath = Path.Combine(_dataDir, "Win11Upgrade.exe");
|
|
using var client = new HttpClient();
|
|
var bytes = client.GetByteArrayAsync("https://go.microsoft.com/fwlink/?linkid=2171764").Result;
|
|
if (bytes.Length < 1024 * 1024) return Task.FromResult("Download fehlgeschlagen");
|
|
File.WriteAllBytes(exePath, bytes);
|
|
|
|
var fullUser = NotificationService.GetLoggedOnUser();
|
|
if (!string.IsNullOrEmpty(fullUser))
|
|
{
|
|
RunSchtasks("/delete /tn \"IT Nexus Win11 Upgrade\" /f");
|
|
RunSchtasks($"/create /tn \"IT Nexus Win11 Upgrade\" /tr \"\\\"{exePath}\\\" /skipeula /auto upgrade\" /sc ONCE /st {DateTime.Now.AddSeconds(20):HH:mm} /ru \"{fullUser}\" /it /rl HIGHEST /f");
|
|
}
|
|
else
|
|
{
|
|
Process.Start(new ProcessStartInfo(exePath, "/quietinstall /skipeula /auto upgrade")
|
|
{ CreateNoWindow = true });
|
|
}
|
|
return Task.FromResult("running");
|
|
}
|
|
|
|
private Task<string> ShellExec(string command)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(command)) return Task.FromResult("Kein Befehl angegeben");
|
|
try
|
|
{
|
|
var psi = new ProcessStartInfo("powershell.exe",
|
|
$"-NonInteractive -NoProfile -ExecutionPolicy Bypass -Command \"{command.Replace("\"", "\\\"")}\"")
|
|
{
|
|
CreateNoWindow = true,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false
|
|
};
|
|
var p = Process.Start(psi)!;
|
|
var stdout = p.StandardOutput.ReadToEnd();
|
|
var stderr = p.StandardError.ReadToEnd();
|
|
p.WaitForExit(30000);
|
|
var output = stdout;
|
|
if (!string.IsNullOrEmpty(stderr)) output += "\n[STDERR] " + stderr;
|
|
return Task.FromResult(string.IsNullOrEmpty(output) ? "(kein Output)" : output.Trim());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Task.FromResult($"Fehler: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private async Task<string> UpdateAgent()
|
|
{
|
|
var bytes = await _api.DownloadSetupAsync(_hostname);
|
|
if (bytes.Length < 512 * 1024) return "Download fehlgeschlagen - Installer zu klein";
|
|
|
|
var setupPath = Path.Combine(_dataDir, "IT-Nexus-Agent-Setup-Update.exe");
|
|
var batchPath = Path.Combine(_dataDir, "update.cmd");
|
|
|
|
await File.WriteAllBytesAsync(setupPath, bytes);
|
|
|
|
// Batch: wartet kurz, führt Installer silent aus, löscht sich selbst
|
|
var batch = $"""
|
|
@echo off
|
|
timeout /t 5 /nobreak > nul
|
|
"{setupPath}" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
|
|
del "{setupPath}" > nul
|
|
del "%~f0"
|
|
""";
|
|
|
|
await File.WriteAllTextAsync(batchPath, batch, System.Text.Encoding.ASCII);
|
|
Process.Start(new ProcessStartInfo("cmd.exe", $"/c \"{batchPath}\"")
|
|
{ CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden });
|
|
|
|
return "Update-Installer gestartet";
|
|
}
|
|
}
|