diff --git a/ReleaseUpdater.Common/Options.cs b/ReleaseUpdater.Common/Options.cs
new file mode 100644
index 0000000..8cc64d3
--- /dev/null
+++ b/ReleaseUpdater.Common/Options.cs
@@ -0,0 +1,34 @@
+using ArgumentsToolkit;
+
+namespace ReleaseUpdater.Common;
+
+/// Параметры CLI для Updater.exe.
+public sealed class Options
+{
+ [Option(nameof(ZipPath), "z", "Путь к скачанному архиву (.zip).", true)]
+ /// Путь к скачанному архиву (.zip).
+ public string ZipPath { get; set; }
+
+ [Option(nameof(InstallPath), "i", "Целевой каталог установки.", true)]
+ /// Целевой каталог установки.
+ public string InstallPath { get; set; }
+
+ [Option(nameof(AppExe), "a", "Имя исполняемого файла приложения для перезапуска", true)]
+ /// Имя исполняемого файла приложения для перезапуска (e.g., MyBot.exe).
+ public string AppExe { get; set; }
+
+ [Option(nameof(RestartDelayMs), "rd", "Миллисекунды ожидания перед перезапуском", false, 500)]
+ /// Необязательно: подождите миллисекунды перед перезапуском.
+ public int RestartDelayMs { get; set; } = 500;
+
+ [Option(nameof(UpdateDelayMs), "ud", "Миллисекунды ожидания перед обновления", false, 500)]
+ /// Необязательно: подождите миллисекунды перед запуском обновления.
+ public int UpdateDelayMs { get; set; } = 500;
+
+ [Option(nameof(WaitProcess), "wp", "PID процесса, завершение которого необходимо дождаться", false)]
+ /// Необязательно: дождаться завершения процесса.
+ public int? WaitProcess { get; set; } = null;
+
+ public static string Usage =>
+ "Usage: Updater.exe --zip --installPath --appExe [--restartDelayMs ] [--updateDelayMs ] [--waitProcess ]";
+}
diff --git a/ReleaseUpdater.Common/ReleaseUpdater.Common.csproj b/ReleaseUpdater.Common/ReleaseUpdater.Common.csproj
new file mode 100644
index 0000000..99658e6
--- /dev/null
+++ b/ReleaseUpdater.Common/ReleaseUpdater.Common.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/ReleaseUpdater.slnx b/ReleaseUpdater.slnx
index 6430c89..d18bd49 100644
--- a/ReleaseUpdater.slnx
+++ b/ReleaseUpdater.slnx
@@ -2,6 +2,8 @@
+
+
diff --git a/ReleaseUpdater/ReleaseUpdater.csproj b/ReleaseUpdater/ReleaseUpdater.csproj
index fa71b7a..00fe7f2 100644
--- a/ReleaseUpdater/ReleaseUpdater.csproj
+++ b/ReleaseUpdater/ReleaseUpdater.csproj
@@ -6,4 +6,12 @@
enable
+
+
+
+
+
+
+
+
diff --git a/ReleaseUpdater/ReleaseUpdaterFacade.cs b/ReleaseUpdater/ReleaseUpdaterFacade.cs
index f333cdc..bedfe27 100644
--- a/ReleaseUpdater/ReleaseUpdaterFacade.cs
+++ b/ReleaseUpdater/ReleaseUpdaterFacade.cs
@@ -90,14 +90,27 @@ public static class ReleaseUpdaterFacade
if (updaterExePath == null) updaterExePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
- var args = $"--zip \"{zipPath}\" --installPath \"{installPath}\" --appExe \"{appExe}\"";
+
+ if (installPath.EndsWith("\\"))
+ {
+ installPath = installPath[0..(installPath.Length - 1)];
+ }
+
+ var updaterOptions = new Common.Options()
+ {
+ ZipPath = zipPath,
+ InstallPath = installPath,
+ AppExe = appExe,
+ };
if (exitCurrentApp)
{
int pid = Process.GetCurrentProcess().Id;
- args += $" --waitProcess \"{pid}\"";
+ updaterOptions.WaitProcess = pid;
}
+ var args = ArgumentsToolkit.ArgumentsParser.ToArguments(updaterOptions, true);
+
var process = Process.Start(new ProcessStartInfo
{
FileName = updaterExePath,
diff --git a/Updater.Test/Program.cs b/Updater.Test/Program.cs
new file mode 100644
index 0000000..ff6c6f7
--- /dev/null
+++ b/Updater.Test/Program.cs
@@ -0,0 +1,21 @@
+using ReleaseUpdater;
+
+namespace Updater.Test;
+
+internal class Program
+{
+ static async Task Main(string[] args)
+ {
+
+ string installPath = AppDomain.CurrentDomain.BaseDirectory;
+ string appExe = "RetailUpdatesBot.exe";
+ string updaterPath = Path.Combine(installPath, "Tools\\Updater.exe");
+
+ var url = "https://git.frigat.duckdns.org/api/v1/repos/automacon/RetailUpdatesBot/releases";
+ var APIKey = "0552a77699d7506711946fc71cc6635515726bd1"; //токен
+
+ await ReleaseUpdaterFacade.UpdateWithExternalAsync(url, APIKey, installPath, appExe, "latest", updaterPath, true);
+
+ Console.ReadKey();
+ }
+}
diff --git a/Updater.Test/Tools/Updater.exe b/Updater.Test/Tools/Updater.exe
new file mode 100644
index 0000000..8b30a80
Binary files /dev/null and b/Updater.Test/Tools/Updater.exe differ
diff --git a/Updater.Test/Updater.Test.csproj b/Updater.Test/Updater.Test.csproj
new file mode 100644
index 0000000..da8130a
--- /dev/null
+++ b/Updater.Test/Updater.Test.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
diff --git a/Updater/Core/ExitCodes.cs b/Updater/Core/ExitCodes.cs
new file mode 100644
index 0000000..c32b4e7
--- /dev/null
+++ b/Updater/Core/ExitCodes.cs
@@ -0,0 +1,15 @@
+namespace Updater.Core;
+
+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;
+}
diff --git a/Updater/Core/Options.cs b/Updater/Core/Options.cs
deleted file mode 100644
index 31ced91..0000000
--- a/Updater/Core/Options.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-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 int UpdateDelayMs { get; init; } = 500;
-
- /// Необязательно: дождаться завершения процесса.
- public int? WaitProcess { get; init; } = null;
-
- public static string Usage =>
- "Usage: Updater.exe --zip --installPath --appExe [--restartDelayMs ] [--updateDelayMs ] [--waitProcess ]";
-
- /// Парсинг 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,
- UpdateDelayMs = dict.TryGetValue("updateDelayMs", out var d2) && int.TryParse(d2, out var n2) ? n2 : 500,
- WaitProcess = dict.TryGetValue("waitProcess", out var pid) && int.TryParse(pid, out var pid_) ? pid_ : null,
- };
- }
-
- 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;
-}
diff --git a/Updater/Core/UpdaterApp.cs b/Updater/Core/UpdaterApp.cs
index d267e59..b4de7c5 100644
--- a/Updater/Core/UpdaterApp.cs
+++ b/Updater/Core/UpdaterApp.cs
@@ -1,4 +1,6 @@
-namespace Updater.Core;
+using ReleaseUpdater.Common;
+
+namespace Updater.Core;
///
/// Управляет потоком обновлений: извлечение, установка, перезапуск.
diff --git a/Updater/Program.cs b/Updater/Program.cs
index cb91585..2be4ef5 100644
--- a/Updater/Program.cs
+++ b/Updater/Program.cs
@@ -1,5 +1,5 @@
-using System.Diagnostics;
-using System.Security.Cryptography;
+using ReleaseUpdater.Common;
+using System.Diagnostics;
using Updater.Core;
namespace Updater;
@@ -9,35 +9,34 @@ internal sealed class Program
static int Main(string[] args)
{
var logger = new ConsoleLogger();
- Options? options;
- try
+
+ var parseResult = ArgumentsToolkit.ArgumentsParser.Parse(args);
+
+ if (!parseResult.Success)
{
- options = Options.Parse(args);
- }
- catch (Exception ex)
- {
- logger.Error($"Arguments error: {ex.Message}");
- Console.WriteLine(Options.Usage);
+ logger.Error($"Arguments error:");
+ parseResult.Errors.ForEach(t => logger.Error(t.Message));
return ExitCodes.InvalidArgs;
}
+ var options = parseResult.Value!;
Thread.Sleep(options.UpdateDelayMs);
if (options.WaitProcess != null)
- try
- {
- using (var proc = Process.GetProcessById(options.WaitProcess.Value))
+ try
{
- logger.Info($"Waiting for the process to complete {options.WaitProcess}...");
- proc.WaitForExit(); // блокирует выполнение до завершения процесса
- logger.Info("Process is completed.");
+ using (var proc = Process.GetProcessById(options.WaitProcess.Value))
+ {
+ logger.Info($"Waiting for the process to complete {options.WaitProcess}...");
+ proc.WaitForExit(); // блокирует выполнение до завершения процесса
+ logger.Info("Process is completed.");
+ }
}
- }
- catch (ArgumentException)
- {
+ catch (ArgumentException)
+ {
logger.Info($"Process with PID {options.WaitProcess} not found.");
- }
+ }
var extractor = new ZipExtractor(logger);
@@ -45,6 +44,8 @@ internal sealed class Program
var procMgr = new ProcessManager(logger);
var app = new UpdaterApp(logger, extractor, installer, procMgr);
- return app.Run(options);
+
+ var exitCode = app.Run(options);
+ return exitCode;
}
}
diff --git a/Updater/Updater.csproj b/Updater/Updater.csproj
index 2150e37..3c2e96f 100644
--- a/Updater/Updater.csproj
+++ b/Updater/Updater.csproj
@@ -7,4 +7,12 @@
enable
+
+
+
+
+
+
+
+
diff --git a/nuget.config b/nuget.config
new file mode 100644
index 0000000..91ba526
--- /dev/null
+++ b/nuget.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file