rework autoupdate to script only

zoom fix
This commit is contained in:
Alex Bezdieniezhnykh
2025-07-06 23:22:21 +03:00
parent 75d3a2412f
commit 6229ca8a03
12 changed files with 179 additions and 80 deletions
+19 -9
View File
@@ -126,9 +126,26 @@ public class CanvasEditor : Canvas
public void SetImageSource(ImageSource? source) public void SetImageSource(ImageSource? source)
{ {
SetZoom();
_backgroundImage.Source = source; _backgroundImage.Source = source;
} }
private void SetZoom(Matrix? matrix = null)
{
if (matrix == null)
{
_matrixTransform.Matrix = Matrix.Identity;
_isZoomedIn = false;
}
else
{
_matrixTransform.Matrix = matrix.Value;
_isZoomedIn = true;
}
foreach (var detection in CurrentDetections)
detection.UpdateAdornerScale(scale: _matrixTransform.Matrix.M11);
}
private void CanvasWheel(object sender, MouseWheelEventArgs e) private void CanvasWheel(object sender, MouseWheelEventArgs e)
{ {
if (Keyboard.Modifiers != ModifierKeys.Control) if (Keyboard.Modifiers != ModifierKeys.Control)
@@ -139,19 +156,12 @@ public class CanvasEditor : Canvas
var matrix = _matrixTransform.Matrix; var matrix = _matrixTransform.Matrix;
if (scale < 1 && matrix.M11 * scale < 1.0) if (scale < 1 && matrix.M11 * scale < 1.0)
{ SetZoom();
_matrixTransform.Matrix = Matrix.Identity;
_isZoomedIn = false;
}
else else
{ {
matrix.ScaleAt(scale, scale, mousePos.X, mousePos.Y); matrix.ScaleAt(scale, scale, mousePos.X, mousePos.Y);
_matrixTransform.Matrix = matrix; SetZoom(matrix);
_isZoomedIn = true;
} }
foreach (var detection in CurrentDetections)
detection.UpdateAdornerScale(scale: _matrixTransform.Matrix.M11);
} }
private void Init(object sender, RoutedEventArgs e) private void Init(object sender, RoutedEventArgs e)
+10 -2
View File
@@ -4,7 +4,8 @@ using MessagePack;
namespace Azaion.Common.DTO; namespace Azaion.Common.DTO;
[MessagePackObject] [MessagePackObject]
public class ApiCredentials : EventArgs [Verb("credsManual", HelpText = "Manual Credentials")]
public class ApiCredentials
{ {
[Key(nameof(Email))] [Key(nameof(Email))]
[Option('e', "email", Required = true, HelpText = "User Email")] [Option('e', "email", Required = true, HelpText = "User Email")]
@@ -13,4 +14,11 @@ public class ApiCredentials : EventArgs
[Key(nameof(Password))] [Key(nameof(Password))]
[Option('p', "pass", Required = true, HelpText = "User Password")] [Option('p', "pass", Required = true, HelpText = "User Password")]
public string Password { get; set; } = null!; public string Password { get; set; } = null!;
} }
[Verb("credsEncrypted", isDefault: true, HelpText = "Encrypted Credentials")]
public class ApiCredentialsEncrypted
{
[Option('c', "creds", Group = "auto", HelpText = "Encrypted Creds")]
public string Creds { get; set; } = null!;
}
+1 -2
View File
@@ -1,9 +1,8 @@
namespace Azaion.Common.DTO; namespace Azaion.Common.DTO;
public class DirectoriesConfig public class DirectoriesConfig
{ {
public string ApiResourcesDirectory { get; set; } = null!; public string? ApiResourcesDirectory { get; set; } = null!;
public string VideosDirectory { get; set; } = null!; public string VideosDirectory { get; set; } = null!;
public string LabelsDirectory { get; set; } = null!; public string LabelsDirectory { get; set; } = null!;
+59
View File
@@ -0,0 +1,59 @@
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
namespace Azaion.Common;
public class Security
{
private static string GenDefaultKey()
{
var date = DateTime.UtcNow;
return $"sAzaion_default_dfvkjhg_{date:yyyy}-{date:MM}_{date:dd}_{date:HH}_key";
}
public static string Encrypt<T>(T model, string? key = null) where T : class
{
var json = JsonConvert.SerializeObject(model);
var inputBytes = Encoding.UTF8.GetBytes(json);
var keyBytes = SHA256.HashData(Encoding.UTF8.GetBytes(key ?? GenDefaultKey()));
var iv = RandomNumberGenerator.GetBytes(16);
using var aes = Aes.Create();
aes.Key = keyBytes;
aes.IV = iv;
aes.Mode = CipherMode.CFB;
aes.Padding = PaddingMode.ISO10126;
using var encryptor = aes.CreateEncryptor();
var ciphertext = encryptor.TransformFinalBlock(inputBytes, 0, inputBytes.Length);
var result = new byte[iv.Length + ciphertext.Length];
iv.CopyTo(result, 0);
ciphertext.CopyTo(result, iv.Length);
return Convert.ToBase64String(result);
}
public static T Decrypt<T>(string encryptedData, string? key = null) where T : class
{
var ciphertextWithIv = Convert.FromBase64String(encryptedData);
var keyBytes = SHA256.HashData(Encoding.UTF8.GetBytes(key ?? GenDefaultKey()));
var iv = ciphertextWithIv[..16];
var ciphertext = ciphertextWithIv[16..];
using var aes = Aes.Create();
aes.Key = keyBytes;
aes.IV = iv;
aes.Mode = CipherMode.CFB;
aes.Padding = PaddingMode.ISO10126;
using var decryptor = aes.CreateDecryptor();
var plaintext = decryptor.TransformFinalBlock(ciphertext, 0, ciphertext.Length);
var json = Encoding.UTF8.GetString(plaintext);
return JsonConvert.DeserializeObject<T>(json)!;
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ from PyInstaller.utils.hooks import collect_all
datas = [('venv\\Lib\\site-packages\\cv2', 'cv2')] datas = [('venv\\Lib\\site-packages\\cv2', 'cv2')]
binaries = [] binaries = []
hiddenimports = ['constants_inf', 'file_data', 'remote_command_inf', 'remote_command_handler_inf', 'annotation', 'loader_client', 'ai_config', 'tensorrt_engine', 'onnx_engine', 'inference_engine', 'inference', 'main-inf'] hiddenimports = ['constants_inf', 'file_data', 'remote_command_inf', 'remote_command_handler_inf', 'annotation', 'loader_client', 'ai_config', 'tensorrt_engine', 'onnx_engine', 'inference_engine', 'inference']
hiddenimports += collect_submodules('cv2') hiddenimports += collect_submodules('cv2')
tmp_ret = collect_all('psutil') tmp_ret = collect_all('psutil')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
-6
View File
@@ -46,11 +46,5 @@ public partial class App
host.Services.GetRequiredService<Login>().Show(); host.Services.GetRequiredService<Login>().Show();
} }
//AFter:
//_loaderClient.Login(credentials);
//_loaderClient.Dispose();
} }
+8 -1
View File
@@ -24,7 +24,6 @@
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
<PackageReference Include="NetMQ" Version="4.0.1.13" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.1" /> <PackageReference Include="Serilog.Extensions.Logging" Version="9.0.1" />
@@ -37,6 +36,14 @@
<Content Include="loaderconfig.json"> <Content Include="loaderconfig.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<None Remove="updater.cmd" />
<Content Include="updater.cmd">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Azaion.Common\Azaion.Common.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+22 -28
View File
@@ -6,6 +6,7 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Azaion.Common;
using MessagePack; using MessagePack;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@@ -57,22 +58,34 @@ public partial class Login
TbStatus.Foreground = Brushes.Black; TbStatus.Foreground = Brushes.Black;
var installerVersion = await GetInstallerVer(); var installerVersion = await GetInstallerVer();
var localVersion = GetLocalVer(); var localVersion = GetLocalVer();
var credsEncrypted = Security.Encrypt(creds);
if (installerVersion > localVersion) if (installerVersion > localVersion)
{ {
TbStatus.Text = $"Updating from {localVersion} to {installerVersion}..."; TbStatus.Text = $"Updating from {localVersion} to {installerVersion}...";
await DownloadAndRunInstaller(); var (installerName, stream) = await _azaionApi.DownloadInstaller(_dirConfig?.SuiteInstallerDirectory ?? "");
TbStatus.Text = $"Installed {installerVersion}!"; var localFileStream = new FileStream(installerName, FileMode.Create, FileAccess.Write);
await stream.CopyToAsync(localFileStream);
localFileStream.Close();
stream.Close();
Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c updater.cmd {Process.GetCurrentProcess().Id} {installerName} {Constants.AZAION_SUITE_EXE} \"{credsEncrypted}\""
});
} }
else else
{
TbStatus.Text = "Your version is up to date!"; TbStatus.Text = "Your version is up to date!";
Process.Start(Constants.AZAION_SUITE_EXE, $"-e {creds.Email} -p {creds.Password}"); Process.Start(Constants.AZAION_SUITE_EXE, $"-c {credsEncrypted}");
await Task.Delay(800); await Task.Delay(800);
TbStatus.Text = "Loading..."; TbStatus.Text = "Loading...";
while (!Process.GetProcessesByName(Constants.INFERENCE_EXE).Any()) while (!Process.GetProcessesByName(Constants.INFERENCE_EXE).Any())
await Task.Delay(500); await Task.Delay(500);
await Task.Delay(1500); await Task.Delay(1500);
}
Close(); Close();
} }
catch (Exception exception) catch (Exception exception)
@@ -146,26 +159,7 @@ public partial class Login
throw; throw;
} }
} }
private async Task DownloadAndRunInstaller()
{
var (installerName, stream) = await _azaionApi.DownloadInstaller(_dirConfig?.SuiteInstallerDirectory ?? "");
var localFileStream = new FileStream(installerName, FileMode.Create, FileAccess.Write);
await stream.CopyToAsync(localFileStream);
localFileStream.Close();
stream.Close();
var processInfo = new ProcessStartInfo(installerName)
{
UseShellExecute = true,
Arguments = "/VERYSILENT"
};
var process = Process.Start(processInfo);
await process!.WaitForExitAsync();
File.Delete(installerName);
}
private async Task<Version> GetInstallerVer() private async Task<Version> GetInstallerVer()
{ {
TbStatus.Text = "Checking for the newer version..."; TbStatus.Text = "Checking for the newer version...";
+39
View File
@@ -0,0 +1,39 @@
@echo off
setlocal
REM Verify that all four arguments were provided
if "%~4"=="" (
echo Error: Missing arguments.
echo Usage: %0 ^<parent_pid^> ^<installer_path^> ^<app_path^> ^<encrypted_creds^>
exit /b 1
)
set "PARENT_PID=%1"
set "INSTALLER_PATH=%2"
set "MAIN_APP_PATH=%3"
set "CREDS=%~4"
:WAIT_FOR_PARENT_EXIT
echo Waiting for parent process (PID: %PARENT_PID%) to close...
tasklist /fi "pid eq %PARENT_PID%" | find "%PARENT_PID%" >nul
if %errorlevel% == 0 (
timeout /t 1 /nobreak >nul
goto WAIT_FOR_PARENT_EXIT
)
start "" /wait "%INSTALLER_PATH%" /VERYSILENT
del "%INSTALLER_PATH%"
echo Installed new version %INSTALLER_PATH%
start "" "%MAIN_APP_PATH%" -c "%CREDS%"
echo Loading...
:WAIT_FOR_APP_START
timeout /t 1 /nobreak >nul
tasklist /fi "imagename eq azaion-inference.exe" | find "azaion-inference.exe" >nul
if %errorlevel% neq 0 goto WAIT_FOR_APP_START
timeout /t 5 /nobreak >nul
echo Process started.
endlocal
+16 -27
View File
@@ -54,11 +54,12 @@ public partial class App
rollingInterval: RollingInterval.Day) rollingInterval: RollingInterval.Day)
.CreateLogger(); .CreateLogger();
Parser.Default.ParseArguments<ApiCredentials>(e.Args) Parser.Default.ParseArguments<ApiCredentials, ApiCredentialsEncrypted>(e.Args)
.WithParsed(Start) .WithParsed<ApiCredentials>(Start)
.WithParsed<ApiCredentialsEncrypted>(StartEncrypted)
.WithNotParsed(ErrorHandling); .WithNotParsed(ErrorHandling);
} }
private void ErrorHandling(IEnumerable<Error> obj) private void ErrorHandling(IEnumerable<Error> obj)
{ {
Log.Fatal($"Error happened: {string.Join(",", obj.Select(x => Log.Fatal($"Error happened: {string.Join(",", obj.Select(x =>
@@ -70,30 +71,11 @@ public partial class App
Current.Shutdown(); Current.Shutdown();
} }
private Stream GetSystemConfig(LoaderClient loaderClient, string apiDir) private Stream GetConfig(LoaderClient loaderClient, string filename, string? apiDir)
{ {
try try
{ {
return loaderClient.LoadFile("config.system.json", apiDir); return loaderClient.LoadFile(filename, apiDir ?? "");
}
catch (Exception e)
{
Log.Logger.Error(e, e.Message);
return new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
{
AnnotationConfig = Constants.DefaultAnnotationConfig,
AIRecognitionConfig = Constants.DefaultAIRecognitionConfig,
GpsDeniedConfig = Constants.DefaultGpsDeniedConfig,
ThumbnailConfig = Constants.DefaultThumbnailConfig,
})));
}
}
private Stream GetSecuredConfig(LoaderClient loaderClient, string apiDir)
{
try
{
return loaderClient.LoadFile("config.secured.json", apiDir);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -102,6 +84,13 @@ public partial class App
} }
} }
private void StartEncrypted(ApiCredentialsEncrypted credsEncrypted)
{
Log.Logger.Information(credsEncrypted.Creds);
Start(Security.Decrypt<ApiCredentials>(credsEncrypted.Creds));
}
private void Start(ApiCredentials credentials) private void Start(ApiCredentials credentials)
{ {
try try
@@ -109,8 +98,8 @@ public partial class App
new ConfigUpdater().CheckConfig(); new ConfigUpdater().CheckConfig();
var initConfig = Constants.ReadInitConfig(Log.Logger); var initConfig = Constants.ReadInitConfig(Log.Logger);
var apiDir = initConfig.DirectoriesConfig.ApiResourcesDirectory; var apiDir = initConfig.DirectoriesConfig.ApiResourcesDirectory;
_loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _mainCTokenSource.Token); _loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _mainCTokenSource.Token);
_loaderClient.StartClient(); _loaderClient.StartClient();
_loaderClient.Connect(); _loaderClient.Connect();
_loaderClient.Login(credentials); _loaderClient.Login(credentials);
@@ -121,8 +110,8 @@ public partial class App
.ConfigureAppConfiguration((_, config) => config .ConfigureAppConfiguration((_, config) => config
.AddCommandLine(Environment.GetCommandLineArgs()) .AddCommandLine(Environment.GetCommandLineArgs())
.AddJsonFile(Constants.CONFIG_PATH, optional: true, reloadOnChange: true) .AddJsonFile(Constants.CONFIG_PATH, optional: true, reloadOnChange: true)
.AddJsonStream(GetSystemConfig(_loaderClient, apiDir)) .AddJsonStream(GetConfig(_loaderClient, "config.system.json", apiDir))
.AddJsonStream(GetSecuredConfig(_loaderClient, apiDir))) .AddJsonStream(GetConfig(_loaderClient, "config.secured.json", apiDir)))
.UseSerilog() .UseSerilog()
.ConfigureServices((context, services) => .ConfigureServices((context, services) =>
{ {
+2 -2
View File
@@ -13,8 +13,8 @@ del dist\config.json
robocopy "dist" "dist-azaion" "Azaion.Annotator.dll" "Azaion.Dataset.dll" "Azaion.Common.dll" "Azaion.CommonSecurity.dll" /MOV robocopy "dist" "dist-azaion" "Azaion.Annotator.dll" "Azaion.Dataset.dll" "Azaion.Common.dll" "Azaion.CommonSecurity.dll" /MOV
robocopy "dist" "dist-azaion" "Azaion.Suite.dll" "Azaion.Suite.exe" "Azaion.Suite.runtimeconfig.json" "Azaion.Suite.deps.json" "logo.png" /MOV robocopy "dist" "dist-azaion" "Azaion.Suite.dll" "Azaion.Suite.exe" "Azaion.Suite.runtimeconfig.json" "Azaion.Suite.deps.json" "logo.png" /MOV
robocopy "Azaion.LoaderUI\bin\Release\net8.0-windows\win-x64\publish" "dist-dlls" "Azaion.LoaderUI.dll" "Azaion.LoaderUI.exe" "Azaion.LoaderUI.runtimeconfig.json" ^ robocopy "Azaion.LoaderUI\bin\Release\net8.0-windows\win-x64\publish" "dist-azaion" "Azaion.LoaderUI.dll" "Azaion.LoaderUI.exe" "Azaion.LoaderUI.runtimeconfig.json" "Azaion.LoaderUI.deps.json" "loaderconfig.json" /MOV
"Azaion.LoaderUI.deps.json" "loaderconfig.json" robocopy "Azaion.LoaderUI\bin\Release\net8.0-windows\win-x64\publish" "dist-dlls" "updater.cmd" /MOV
move dist\config.production.json dist-azaion\config_updated.json move dist\config.production.json dist-azaion\config_updated.json
+2 -2
View File
@@ -19,8 +19,8 @@ echo building and upload iterative installer...
iscc build\installer.iterative.iss iscc build\installer.iterative.iss
call build\upload.cmd "suite-dev" call build\upload.cmd "suite-dev"
echo building full installer @rem echo building full installer
iscc build\installer.full.iss @rem iscc build\installer.full.iss
cd /d %CURRENT_DIR% cd /d %CURRENT_DIR%
echo Done! echo Done!