namespace Updater.Core; /// Параметры CLI для Updater.exe. public sealed class Options { /// Путь к скачанному архиву (.zip). public required string ZipPath { get; init; } /// Целевой каталог установки. public required string InstallPath { get; init; } /// Имя исполняемого файла приложения для перезапуска (e.g., MyBot.exe). public required string AppExe { get; init; } /// Необязательно: подождите миллисекунды перед перезапуском (льготный период). public int RestartDelayMs { get; init; } = 500; public static string Usage => "Usage: Updater.exe --zip --installPath --appExe [--restartDelayMs ]"; /// Папрсинг CLI аргументов в Options. public static Options Parse(string[] args) { var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < args.Length; i++) { if (!args[i].StartsWith("--")) continue; var key = args[i][2..]; var val = (i + 1 < args.Length && !args[i + 1].StartsWith("--")) ? args[i + 1] : "true"; dict[key] = val; } var zip = Require(dict, "zip"); var install = Require(dict, "installPath"); var exe = Require(dict, "appExe"); if (!File.Exists(zip)) throw new FileNotFoundException("Zip not found", zip); Directory.CreateDirectory(install); return new Options { ZipPath = Path.GetFullPath(zip), InstallPath = Path.GetFullPath(install), AppExe = exe, RestartDelayMs = dict.TryGetValue("restartDelayMs", out var d) && int.TryParse(d, out var n) ? n : 500 }; } private static string Require(IDictionary dict, string key) => dict.TryGetValue(key, out var v) && !string.IsNullOrWhiteSpace(v) ? v : throw new ArgumentException($"Missing --{key}"); } public static class ExitCodes { /// Успешное обновление. public const int Ok = 0; /// Неверные аргументы командной строки. public const int InvalidArgs = 2; /// Ошибка извлечения. public const int ExtractFailed = 3; /// Ошибка установки (копировать/заменить). public const int InstallFailed = 4; /// Ошибка перезапуска. public const int RestartFailed = 5; }