Skip to content

Commit 0e48200

Browse files
authored
feat: compile upgrade to .exe for GeneralUpdate StartApp (#58)
* feat: compile upgrade to .exe via dotnet publish for GeneralUpdate StartApp - Add CompileUpgrade toggle (default true) in SimulateView - When checked: generate upgrade.csproj + Program.cs, dotnet publish to .exe - Client AppName set to upgrade.exe (launchable by GeneralUpdate) - When unchecked: keep upgrade.csx + upgrade.bat (manual mode) - i18n: Sim.CompileUpgrade key for both locales * fix: remove .bat, unchecked uses upgrade.csx directly
1 parent a6c6ee5 commit 0e48200

5 files changed

Lines changed: 106 additions & 14 deletions

File tree

src/Models/SimulateConfigModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ public partial class SimulateConfigModel : ObservableObject
1616
[ObservableProperty] private string _appSecretKey = "dfeb5833-975e-4afb-88f1-6278ee9aeff6";
1717
[ObservableProperty] private string _productId = "2d974e2a-31e6-4887-9bb1-b4689e98c77a";
1818
[ObservableProperty] private string _outputDirectory = string.Empty;
19+
[ObservableProperty] private bool _compileUpgrade = true;
1920
public int ServerPort { get; set; } = 5000;
2021
}

src/Services/ClientGeneratorService.cs

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,9 @@
66

77
namespace GeneralUpdate.Tools.Services;
88

9-
/// <summary>
10-
/// Generates single-file client.csx and upgrade.csx for simulation,
11-
/// using dotnet script with #r directives (exact NuGet version).
12-
/// </summary>
139
public class ClientGeneratorService
1410
{
15-
private const string ClientTemplate = """
11+
private const string ClientScript = """
1612
#r "nuget:GeneralUpdate.ClientCore,10.4.6"
1713
1814
using GeneralUpdate.ClientCore;
@@ -70,7 +66,7 @@ public class ClientGeneratorService
7066
}}
7167
""";
7268

73-
private const string UpgradeTemplate = """
69+
private const string UpgradeScript = """
7470
#r "nuget:GeneralUpdate.Core,10.4.6"
7571
7672
using GeneralUpdate.Core;
@@ -108,28 +104,110 @@ public class ClientGeneratorService
108104
Console.Error.WriteLine(ex);
109105
Environment.Exit(1);
110106
}}
107+
""";
108+
109+
private const string UpgradeCsproj = """
110+
<Project Sdk="Microsoft.NET.Sdk">
111+
<PropertyGroup>
112+
<OutputType>Exe</OutputType>
113+
<TargetFramework>net10.0</TargetFramework>
114+
<Nullable>enable</Nullable>
115+
<ImplicitUsings>enable</ImplicitUsings>
116+
</PropertyGroup>
117+
<ItemGroup>
118+
<PackageReference Include="GeneralUpdate.Core" Version="10.4.6" />
119+
</ItemGroup>
120+
</Project>
121+
""";
122+
123+
private const string UpgradeProgram = """
124+
using GeneralUpdate.Core;
125+
using GeneralUpdate.Common.Shared;
126+
using GeneralUpdate.Common.Internal.Event;
127+
128+
var log = (string msg) => Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {{msg}}");
129+
130+
try
131+
{
132+
log("Upgrade process started");
133+
log("Working directory: " + Environment.CurrentDirectory);
134+
135+
await new GeneralUpdateBootstrap()
136+
.AddListenerMultiDownloadStatistics((_, e) =>
137+
{
138+
var v = e.Version as GeneralUpdate.Common.Shared.Object.VersionInfo;
139+
log($"Download: {{v?.Version}} {{e.ProgressPercentage}}%");
140+
})
141+
.AddListenerMultiAllDownloadCompleted((_, e) =>
142+
{
143+
log(e.IsAllDownloadCompleted ? "Downloads done" : "Download failed");
144+
})
145+
.AddListenerException((_, e) =>
146+
{
147+
log($"ERROR: {{e.Exception}}");
148+
})
149+
.LaunchAsync();
150+
151+
log("Upgrade process finished successfully");
152+
}
153+
catch (Exception ex)
154+
{
155+
log($"FATAL: {{ex.Message}}");
156+
Console.Error.WriteLine(ex);
157+
Environment.Exit(1);
158+
}
111159
""";
112160

113161
public async Task GenerateAsync(SimulateConfigModel config, string outputDir)
114162
{
115163
var serverUrl = $"http://127.0.0.1:{config.ServerPort}";
164+
var appName = config.CompileUpgrade ? "upgrade.exe" : "upgrade.csx";
116165

117166
await File.WriteAllTextAsync(Path.Combine(outputDir, "client.csx"),
118-
string.Format(ClientTemplate,
167+
string.Format(ClientScript,
119168
EscapeForCSharp(config.AppDirectory),
120169
serverUrl,
121-
"upgrade.csx",
170+
appName,
122171
"client.csx",
123172
config.CurrentVersion,
124173
"1.0.0.0",
125174
config.ProductId,
126175
config.AppSecretKey),
127176
Encoding.UTF8);
128177

129-
await File.WriteAllTextAsync(Path.Combine(outputDir, "upgrade.csx"),
130-
string.Format(UpgradeTemplate,
131-
EscapeForCSharp(config.AppDirectory)),
132-
Encoding.UTF8);
178+
if (config.CompileUpgrade)
179+
{
180+
var upgradeDir = Path.Combine(outputDir, "upgrade");
181+
Directory.CreateDirectory(upgradeDir);
182+
await File.WriteAllTextAsync(Path.Combine(upgradeDir, "upgrade.csproj"), UpgradeCsproj, Encoding.UTF8);
183+
await File.WriteAllTextAsync(Path.Combine(upgradeDir, "Program.cs"),
184+
UpgradeProgram, Encoding.UTF8);
185+
}
186+
else
187+
{
188+
await File.WriteAllTextAsync(Path.Combine(outputDir, "upgrade.csx"),
189+
string.Format(UpgradeScript, EscapeForCSharp(config.AppDirectory)), Encoding.UTF8);
190+
}
191+
}
192+
193+
public async Task PublishUpgradeAsync(string outputDir)
194+
{
195+
var upgradeDir = Path.Combine(outputDir, "upgrade");
196+
var psi = new System.Diagnostics.ProcessStartInfo("dotnet", "publish -c Release -r win-x64 --self-contained false -o .")
197+
{
198+
WorkingDirectory = upgradeDir,
199+
RedirectStandardOutput = true,
200+
RedirectStandardError = true,
201+
UseShellExecute = false,
202+
CreateNoWindow = true
203+
};
204+
var p = System.Diagnostics.Process.Start(psi)!;
205+
await p.WaitForExitAsync();
206+
// Copy the published exe to the output root
207+
var src = Path.Combine(upgradeDir, "upgrade.exe");
208+
var dst = Path.Combine(outputDir, "upgrade.exe");
209+
if (File.Exists(src))
210+
File.Copy(src, dst, true);
133211
}
134212

135213
private static string EscapeForCSharp(string s) =>

src/Services/LocalizationService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public string this[string key]
137137
["Sim.ValidateDirs"] = "请填写所有必填项",
138138
["Sim.DotnetCheck"] = "需要 .NET 10.0 SDK,请先安装",
139139
["Sim.AutoRun"] = "自动启动服务器并运行客户端",
140+
["Sim.CompileUpgrade"] = "编译 upgrade 为 .exe",
140141
["Sim.ManualMode"] = "服务器/客户端已生成,可手动运行:\ndotnet script client.csx",
141142
["Sim.Starting"] = "正在启动模拟...",
142143
["Sim.Completed"] = "模拟完成 ({0:F1}s)",
@@ -236,6 +237,7 @@ public string this[string key]
236237
["Sim.ValidateDirs"] = "Please fill in all required fields",
237238
["Sim.DotnetCheck"] = ".NET 10.0 SDK is required. Please install it first.",
238239
["Sim.AutoRun"] = "Auto-start server and run client",
240+
["Sim.CompileUpgrade"] = "Compile upgrade to .exe",
239241
["Sim.ManualMode"] = "Server/client generated. Run manually:\ndotnet script client.csx",
240242
["Sim.Starting"] = "Starting simulation...",
241243
["Sim.Completed"] = "Simulation completed ({0:F1}s)",

src/Services/SimulationService.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,19 @@ public async Task<SimulationResult> RunAsync(
3636
Directory.CreateDirectory(config.OutputDirectory);
3737

3838
// 3. Generate scripts
39-
Log("STEP 3: Generating client.csx and upgrade.csx", progress);
39+
Log("STEP 3: Generating scripts", progress);
4040
await _generator.GenerateAsync(config, config.OutputDirectory);
4141
Log($" client.csx → {config.OutputDirectory}", progress);
42-
Log($" upgrade.csx → {config.OutputDirectory}", progress);
42+
if (config.CompileUpgrade)
43+
{
44+
Log(" Compiling upgrade to .exe (dotnet publish)...", progress);
45+
await _generator.PublishUpgradeAsync(config.OutputDirectory);
46+
Log(" upgrade.exe ready", progress);
47+
}
48+
else
49+
{
50+
Log($" upgrade.csx → {config.OutputDirectory}", progress);
51+
}
4352

4453
// 4. Start server
4554
Log("STEP 4: Starting local server", progress);

src/Views/SimulateView.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
</Border>
8383

8484
<!-- Run -->
85+
<CheckBox Content="{Binding Source={x:Static svc:LocalizationService.Instance}, Path=[Sim.CompileUpgrade]}"
86+
IsChecked="{Binding Config.CompileUpgrade}"/>
8587
<Button Content="{Binding Source={x:Static svc:LocalizationService.Instance}, Path=[Sim.Start]}"
8688
Command="{Binding StartSimulationCommand}"
8789
IsEnabled="{Binding !IsRunning}" Height="40" FontSize="14" HorizontalAlignment="Stretch"/>

0 commit comments

Comments
 (0)