|
7 | 7 |
|
8 | 8 | try |
9 | 9 | { |
10 | | - Console.WriteLine("=== GeneralUpdate Client Test ==="); |
| 10 | + Console.WriteLine("=== GeneralUpdate Client Test (Silent Mode) ==="); |
11 | 11 | Console.WriteLine($"Started at {DateTime.Now}"); |
12 | 12 | Console.WriteLine($"Running from: {AppDomain.CurrentDomain.BaseDirectory}"); |
13 | 13 |
|
|
17 | 17 | var appSecretKey = Environment.GetEnvironmentVariable("APP_SECRET_KEY") ?? "dfeb5833-975e-4afb-88f1-6278ee9aeff6"; |
18 | 18 |
|
19 | 19 | Console.WriteLine($"UpdateUrl: {updateUrl}"); |
| 20 | + Console.WriteLine($"Silent mode: ENABLED (poll every 1 minute)"); |
20 | 21 | Console.WriteLine(); |
21 | 22 |
|
22 | | - // Identity metadata (MainAppName, ClientVersion, UpdateAppName, UpdatePath, …) |
23 | | - // is auto-discovered from generalupdate.manifest.json (generated by GeneralUpdate.Tools). |
24 | | - await new GeneralUpdateBootstrap() |
| 23 | + // Silent mode: polls server in background, prepares update, launches Upgrade on exit. |
| 24 | + var bootstrap = await new GeneralUpdateBootstrap() |
25 | 25 | .SetSource(updateUrl, appSecretKey, reportUrl) |
26 | 26 | .SetOption(Option.AppType, AppType.Client) |
| 27 | + .SetOption(Option.Silent, true) |
| 28 | + .SetOption(Option.SilentPollIntervalMinutes, 1) |
27 | 29 | .Hooks<ClientTestHooks>() |
28 | 30 | .AddListenerMultiDownloadStatistics(OnDownloadStatistics) |
29 | 31 | .AddListenerMultiDownloadCompleted(OnDownloadCompleted) |
|
33 | 35 | .AddListenerUpdateInfo(OnUpdateInfo) |
34 | 36 | .LaunchAsync(); |
35 | 37 |
|
36 | | - Console.WriteLine("Client test completed."); |
| 38 | + var orchestrator = bootstrap.SilentOrchestrator; |
| 39 | + |
| 40 | + Console.WriteLine(); |
| 41 | + Console.WriteLine("╔════════════════════════════════════════════╗"); |
| 42 | + Console.WriteLine("║ Silent poll running in background. ║"); |
| 43 | + Console.WriteLine("║ Press Ctrl+C or Enter to exit. ║"); |
| 44 | + Console.WriteLine("║ On exit, Upgrade process will be launched ║"); |
| 45 | + Console.WriteLine("║ if an update has been prepared. ║"); |
| 46 | + Console.WriteLine("╚════════════════════════════════════════════╝"); |
| 47 | + Console.WriteLine(); |
| 48 | + |
| 49 | + // Keep the process alive so the background poll loop can work. |
| 50 | + // When the user presses Ctrl+C or Enter, the process exits and |
| 51 | + // ProcessExit fires, which triggers the upgrade launch. |
| 52 | + var cts = new CancellationTokenSource(); |
| 53 | + Console.CancelKeyPress += (_, e) => |
| 54 | + { |
| 55 | + Console.WriteLine(); |
| 56 | + Console.WriteLine("[Shutdown] Ctrl+C pressed. Exiting..."); |
| 57 | + e.Cancel = true; // Prevent immediate kill — let ProcessExit fire |
| 58 | + cts.Cancel(); |
| 59 | + }; |
| 60 | + |
| 61 | + try |
| 62 | + { |
| 63 | + await Task.Delay(Timeout.Infinite, cts.Token); |
| 64 | + } |
| 65 | + catch (OperationCanceledException) |
| 66 | + { |
| 67 | + // Expected on Ctrl+C — graceful shutdown |
| 68 | + } |
| 69 | + |
| 70 | + // Explicitly launch the upgrade process before exiting. |
| 71 | + // ProcessExit may not fire reliably in all scenarios (e.g. console Ctrl+C), |
| 72 | + // so we call TryLaunchUpgrade() directly as the primary launch path. |
| 73 | + // If ProcessExit also fires later, the _updaterStarted guard prevents a double-launch. |
| 74 | + Console.WriteLine("[Shutdown] Launching upgrade process..."); |
| 75 | + if (orchestrator != null && orchestrator.HasPreparedUpdate) |
| 76 | + { |
| 77 | + var launched = orchestrator.TryLaunchUpgrade(); |
| 78 | + Console.WriteLine(launched |
| 79 | + ? "[Shutdown] Upgrade process launched successfully." |
| 80 | + : "[Shutdown] No update prepared or upgrade already launched."); |
| 81 | + } |
| 82 | + else |
| 83 | + { |
| 84 | + Console.WriteLine("[Shutdown] No orchestrator or no update prepared."); |
| 85 | + } |
| 86 | + |
| 87 | + Console.WriteLine("[Shutdown] Client test exiting gracefully."); |
37 | 88 | } |
38 | 89 | catch (Exception ex) |
39 | 90 | { |
|
0 commit comments