diff --git a/src/c#/GeneralUpdate.Core/Download/DownloadPlanBuilder.cs b/src/c#/GeneralUpdate.Core/Download/DownloadPlanBuilder.cs index 038d0e4e..37c11abd 100644 --- a/src/c#/GeneralUpdate.Core/Download/DownloadPlanBuilder.cs +++ b/src/c#/GeneralUpdate.Core/Download/DownloadPlanBuilder.cs @@ -22,6 +22,7 @@ public static class DownloadPlanBuilder public static DownloadPlan Build(IEnumerable assets, string currentVersion) { if (assets == null) return DownloadPlan.Empty; + if (ParseVersion(currentVersion) == null) return DownloadPlan.Empty; // 1. Filter out frozen packages var active = assets diff --git a/src/c#/GeneralUpdate.Core/Download/MultiEventArgs/UpdateInfoEventArgs.cs b/src/c#/GeneralUpdate.Core/Download/MultiEventArgs/UpdateInfoEventArgs.cs index b0dfef83..89db4e3b 100644 --- a/src/c#/GeneralUpdate.Core/Download/MultiEventArgs/UpdateInfoEventArgs.cs +++ b/src/c#/GeneralUpdate.Core/Download/MultiEventArgs/UpdateInfoEventArgs.cs @@ -3,7 +3,7 @@ namespace GeneralUpdate.Core.Download; -public class UpdateInfoEventArgs(VersionRespDTO info) : EventArgs +public class UpdateInfoEventArgs(VersionRespDTO? info = null) : EventArgs { - public VersionRespDTO Info { get; private set; } = info; + public VersionRespDTO? Info { get; private set; } = info; } diff --git a/src/c#/GeneralUpdate.Core/Download/Orchestrators/DefaultDownloadOrchestrator.cs b/src/c#/GeneralUpdate.Core/Download/Orchestrators/DefaultDownloadOrchestrator.cs index d398109e..1e1fcb6f 100644 --- a/src/c#/GeneralUpdate.Core/Download/Orchestrators/DefaultDownloadOrchestrator.cs +++ b/src/c#/GeneralUpdate.Core/Download/Orchestrators/DefaultDownloadOrchestrator.cs @@ -40,9 +40,11 @@ public async Task ExecuteAsync( if (plan == null || !plan.HasAssets) return new DownloadReport(Array.Empty(), 0, TimeSpan.Zero, 0, 0); + Directory.CreateDirectory(destDir); + var sw = Stopwatch.StartNew(); var results = new List(); - var sem = new SemaphoreSlim(maxConcurrency); + using var sem = new SemaphoreSlim(maxConcurrency); long totalBytes = 0; var tasks = plan.Assets.Select(async asset => diff --git a/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs b/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs index 79636488..8c31acd9 100644 --- a/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs @@ -172,9 +172,19 @@ private async Task ExecuteStandardWorkflowAsync(Encoding encoding, int timeout) } // Build process info for the upgrade process + // Convert DownloadAsset list to VersionInfo for ProcessInfo compatibility + var downloadVersions = downloadPlan.Assets.Select(a => new VersionInfo + { + Name = a.Name, + Hash = a.SHA256, + Url = a.Url, + Version = a.Version, + Format = "ZIP" + }).ToList(); + _configInfo.ProcessInfo = JsonSerializer.Serialize( ConfigurationMapper.MapToProcessInfo( - _configInfo, new List(), + _configInfo, downloadVersions, BlackListManager.Instance.BlackFormats.ToList(), BlackListManager.Instance.BlackFiles.ToList(), BlackListManager.Instance.SkipDirectorys.ToList()), @@ -185,17 +195,21 @@ private async Task ExecuteStandardWorkflowAsync(Encoding encoding, int timeout) _osStrategy!.Create(_configInfo); - // Download via orchestrator (replaces old DownloadManager) + // Download via orchestrator GeneralTracer.Info($"ClientUpdateStrategy: downloading {downloadPlan.Assets.Count} asset(s)."); - var httpClient = new System.Net.Http.HttpClient(); - try + if (_orchestrator != null) { - var orchestrator = new Download.Orchestrators.DefaultDownloadOrchestrator(httpClient); - await orchestrator.ExecuteAsync(downloadPlan, _configInfo.TempPath).ConfigureAwait(false); + await _orchestrator.ExecuteAsync(downloadPlan, _configInfo.TempPath).ConfigureAwait(false); } - finally + else { - httpClient.Dispose(); + var httpClient = new System.Net.Http.HttpClient(); + try + { + var orchestrator = new Download.Orchestrators.DefaultDownloadOrchestrator(httpClient); + await orchestrator.ExecuteAsync(downloadPlan, _configInfo.TempPath).ConfigureAwait(false); + } + finally { httpClient.Dispose(); } } await SafeReportDownloadCompletedAsync(hooksCtx).ConfigureAwait(false); diff --git a/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs b/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs index b87c8cbd..34fd2cd6 100644 --- a/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs @@ -117,17 +117,32 @@ public void StartApp() private async Task DownloadVersionsAsync(List versions) { - var assets = versions.Select(v => new Download.Models.DownloadAsset( - Name: v.PacketName ?? v.Version ?? "unknown", - Url: v.Url ?? string.Empty, - Size: 0, - SHA256: v.Hash, - Version: v.Version ?? "0.0.0" - )).ToList(); + var assets = versions.Select(v => + { + if (string.IsNullOrWhiteSpace(v.Url)) + throw new InvalidOperationException( + $"OSS version '{v.PacketName ?? v.Version}' has no download URL."); + + // Use PacketName.zip as the filename to match Decompress() expectations. + // The orchestrator falls back to {Name}.{Version} when URL-based extraction fails, + // so we set Version to "zip" to produce e.g. "myapp.zip.zip". + // Better: set Name to the zip filename directly. + var zipName = $"{v.PacketName ?? v.Version}zip"; + if (!zipName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) + zipName += ".zip"; + + return new Download.Models.DownloadAsset( + Name: zipName, + Url: v.Url, + Size: 0, + SHA256: v.Hash, + Version: v.Version ?? "0.0.0" + ); + }).ToList(); var plan = new Download.Models.DownloadPlan(assets, false); - var httpClient = new System.Net.Http.HttpClient(); + var httpClient = new System.Net.Http.HttpClient { Timeout = TimeSpan.FromSeconds(TimeOut) }; try { var orchestrator = new Download.Orchestrators.DefaultDownloadOrchestrator(httpClient);