From 2d0ec208a497f6df1f8a2c817b0b57f9c0e5611e Mon Sep 17 00:00:00 2001 From: JusterZhu Date: Thu, 21 May 2026 14:49:41 +0800 Subject: [PATCH 1/2] fix: use OutputDirectory for --install-path instead of AppDirectory Client.exe receives --install-path to determine where Upgrade.exe lives for StartApp. Previously this pointed to config.AppDirectory (the real user path), but Upgrade.exe was only copied to OutputDirectory during simulation. Change to OutputDirectory so the simulation doesn't depend on external file system state. --- src/Services/SimulationService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Services/SimulationService.cs b/src/Services/SimulationService.cs index ab757ee..7d6d625 100644 --- a/src/Services/SimulationService.cs +++ b/src/Services/SimulationService.cs @@ -88,7 +88,7 @@ public async Task RunAsync( var clientArgs = new List { "--server-url", _server.BaseUrl, - "--install-path", config.AppDirectory, + "--install-path", config.OutputDirectory, "--current-version", config.CurrentVersion, "--app-secret", config.AppSecretKey, "--product-id", config.ProductId, From c18916fd34085c55b098d2c0152257113c9da41e Mon Sep 17 00:00:00 2001 From: JusterZhu Date: Thu, 21 May 2026 15:30:35 +0800 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20remove=20OutputDirectory=20?= =?UTF-8?q?=E2=80=94=20run=20simulation=20entirely=20in=20AppDirectory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All simulation artifacts (Client.exe, Upgrade.exe, .server, report) now live in the same AppDirectory where the update is targeted. Changes: - Remove OutputDirectory from SimulateConfigModel - Replace all config.OutputDirectory references with config.AppDirectory - Remove OutputDirectory validation check - Remove SelectOutputDirCommand and OutputDir UI section - Fix --install-path to use AppDirectory (avoid OneDrive real path issues) Closes the issue where StartApp couldn't find Upgrade.exe because it was looking in a real user path instead of the simulation workspace. --- src/Models/SimulateConfigModel.cs | 1 - src/Services/SimulationService.cs | 20 +++++++++----------- src/ViewModels/SimulateViewModel.cs | 6 ++---- src/Views/SimulateView.axaml | 15 --------------- 4 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/Models/SimulateConfigModel.cs b/src/Models/SimulateConfigModel.cs index 64832c4..3ed1d15 100644 --- a/src/Models/SimulateConfigModel.cs +++ b/src/Models/SimulateConfigModel.cs @@ -15,6 +15,5 @@ public partial class SimulateConfigModel : ObservableObject [ObservableProperty] private int _appType = 1; [ObservableProperty] private string _appSecretKey = "dfeb5833-975e-4afb-88f1-6278ee9aeff6"; [ObservableProperty] private string _productId = "2d974e2a-31e6-4887-9bb1-b4689e98c77a"; - [ObservableProperty] private string _outputDirectory = string.Empty; public int ServerPort { get; set; } = 5000; } diff --git a/src/Services/SimulationService.cs b/src/Services/SimulationService.cs index 7d6d625..2517d4c 100644 --- a/src/Services/SimulationService.cs +++ b/src/Services/SimulationService.cs @@ -30,9 +30,9 @@ public async Task RunAsync( Log("STEP 1: Validating inputs", progress); Validate(config); - // 2. Prepare output - Log($"STEP 2: Preparing {config.OutputDirectory}", progress); - Directory.CreateDirectory(config.OutputDirectory); + // 2. Prepare app directory + Log($"STEP 2: Preparing {config.AppDirectory}", progress); + Directory.CreateDirectory(config.AppDirectory); // 3. Compile test apps to .exe Log("STEP 3: Compiling test apps", progress); @@ -60,15 +60,15 @@ public async Task RunAsync( await DotNetPublishAsync(upgradeProj, exeDir); Log($" Upgrade.exe → {exeDir}", progress); - // Copy to simulation output - var clientDest = Path.Combine(config.OutputDirectory, "Client.exe"); - var upgradeDest = Path.Combine(config.OutputDirectory, "Upgrade.exe"); + // Copy compiled apps into app directory + var clientDest = Path.Combine(config.AppDirectory, "Client.exe"); + var upgradeDest = Path.Combine(config.AppDirectory, "Upgrade.exe"); File.Copy(Path.Combine(exeDir, "ClientSample.exe"), clientDest, true); File.Copy(Path.Combine(exeDir, "UpgradeSample.exe"), upgradeDest, true); // 4. Start server Log("STEP 4: Starting local server", progress); - var serverPatchDir = Path.Combine(config.OutputDirectory, ".server"); + var serverPatchDir = Path.Combine(config.AppDirectory, ".server"); Directory.CreateDirectory(serverPatchDir); var patchName = Path.GetFileName(config.PatchFilePath); var patchDest = Path.Combine(serverPatchDir, patchName); @@ -84,11 +84,11 @@ public async Task RunAsync( // 5. Run client Log("STEP 5: Running Client.exe", progress); - var clientExe = Path.Combine(config.OutputDirectory, "Client.exe"); + var clientExe = Path.Combine(config.AppDirectory, "Client.exe"); var clientArgs = new List { "--server-url", _server.BaseUrl, - "--install-path", config.OutputDirectory, + "--install-path", config.AppDirectory, "--current-version", config.CurrentVersion, "--app-secret", config.AppSecretKey, "--product-id", config.ProductId, @@ -157,8 +157,6 @@ private void Validate(SimulateConfigModel config) throw new DirectoryNotFoundException($"App directory not found: {config.AppDirectory}"); if (!File.Exists(config.PatchFilePath)) throw new FileNotFoundException($"Patch file not found: {config.PatchFilePath}"); - if (string.IsNullOrWhiteSpace(config.OutputDirectory)) - throw new ArgumentException("Output directory is required"); try { var psi = new ProcessStartInfo("dotnet", "--version") { RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true }; diff --git a/src/ViewModels/SimulateViewModel.cs b/src/ViewModels/SimulateViewModel.cs index f51d83c..7fa0c8f 100644 --- a/src/ViewModels/SimulateViewModel.cs +++ b/src/ViewModels/SimulateViewModel.cs @@ -83,14 +83,12 @@ public int AppTypeIndex [RelayCommand] async Task SelectAppDir() { var p = await PickFolder(_loc["Sim.SelectAppDir"]); if (p != null) Config.AppDirectory = p; } [RelayCommand] async Task SelectPatch() { var p = await PickFile(_loc["Sim.SelectPatch"]); if (p != null) Config.PatchFilePath = p; } - [RelayCommand] async Task SelectOutputDir() { var p = await PickFolder(_loc["Sim.SelectOutput"]); if (p != null) Config.OutputDirectory = p; } [RelayCommand] async Task StartSimulation() { if (string.IsNullOrWhiteSpace(Config.AppDirectory)) { Status = _loc["Sim.ValidateDirs"]; return; } if (string.IsNullOrWhiteSpace(Config.PatchFilePath)) { Status = _loc["Sim.ValidateDirs"]; return; } - if (string.IsNullOrWhiteSpace(Config.OutputDirectory)) { Status = _loc["Sim.ValidateDirs"]; return; } IsRunning = true; StartButtonText = "⏳ Running..."; Log.Clear(); Status = _loc["Sim.Starting"]; try @@ -107,7 +105,7 @@ async Task StartSimulation() } L($"Result: {(result.Success ? "PASS" : "FAIL")}"); foreach (var note in result.Notes) L($" Note: {note}"); - var reportPath = await _report.GenerateAsync(Config, result, Config.OutputDirectory); + var reportPath = await _report.GenerateAsync(Config, result, Config.AppDirectory); L(_loc.T("Sim.Report", reportPath)); } catch (Exception ex) @@ -115,7 +113,7 @@ async Task StartSimulation() Status = $"Error: {ex.Message}"; L($"FATAL: {ex}"); var failResult = new SimulationResult { Success = false, ErrorMessage = ex.Message }; - var reportPath = await _report.GenerateAsync(Config, failResult, Config.OutputDirectory); + var reportPath = await _report.GenerateAsync(Config, failResult, Config.AppDirectory); L(_loc.T("Sim.Report", reportPath)); } finally { IsRunning = false; StartButtonText = _loc["Sim.Start"]; } diff --git a/src/Views/SimulateView.axaml b/src/Views/SimulateView.axaml index 85c0156..614d54e 100644 --- a/src/Views/SimulateView.axaml +++ b/src/Views/SimulateView.axaml @@ -66,21 +66,6 @@ - - - - - - - -