diff --git a/src/Services/ClientGeneratorService.cs b/src/Services/ClientGeneratorService.cs
index 252c216..e2e7ee6 100644
--- a/src/Services/ClientGeneratorService.cs
+++ b/src/Services/ClientGeneratorService.cs
@@ -7,28 +7,36 @@
namespace GeneralUpdate.Tools.Services;
///
-/// Generates single-file client.cs and upgrade.cs for simulation,
-/// using dotnet-run (#r nuget:...) without project files.
+/// Generates client and upgrade console projects for simulation,
+/// each with a minimal .csproj + Program.cs using dotnet run --project.
///
public class ClientGeneratorService
{
- private const string ClientTemplate = """
-#r "nuget: GeneralUpdate.ClientCore"
-#r "nuget: GeneralUpdate.Core"
-
-using GeneralUpdate.ClientCore;
-using GeneralUpdate.Common.Shared.Object;
-using GeneralUpdate.Common.Internal.Event;
+ private const string ClientCsproj = """
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+""";
-var log = (string msg) => Console.WriteLine($"[{{DateTime.Now:HH:mm:ss}}] {{msg}}");
+ private const string ClientProgram = """
+var log = (string msg) => Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {msg}");
try
-{{
+{
log("Client started");
log("Install path: {0}");
- var config = new Configinfo
- {{
+ var config = new GeneralUpdate.Common.Shared.Object.Configinfo
+ {
ReportUrl = "{1}/Upgrade/Report",
UpdateUrl = "{1}/Upgrade/Verification",
AppName = "{2}",
@@ -38,107 +46,115 @@ public class ClientGeneratorService
UpgradeClientVersion = "{5}",
ProductId = "{6}",
AppSecretKey = "{7}",
- }};
+ };
- await new GeneralClientBootstrap()
+ await new GeneralUpdate.ClientCore.GeneralClientBootstrap()
.SetConfig(config)
.AddListenerMultiDownloadStatistics((_, e) =>
- {{
- var v = e.Version as VersionInfo;
- log($"Download: {{v?.Version}} {{e.ProgressPercentage}}% {{e.Speed}}/s");
- }})
+ {
+ var v = e.Version as GeneralUpdate.Common.Shared.Object.VersionInfo;
+ log($"Download: {v?.Version} {e.ProgressPercentage}% {e.Speed}/s");
+ })
.AddListenerMultiAllDownloadCompleted((_, e) =>
- {{
- log(e.IsAllDownloadCompleted ? "All downloads completed" : $"Download failed: {{e.FailedVersions.Count}}");
- }})
+ {
+ log(e.IsAllDownloadCompleted ? "All downloads completed" : $"Download failed: {e.FailedVersions.Count}");
+ })
.AddListenerException((_, e) =>
- {{
- log($"ERROR: {{e.Exception}}");
- }})
+ {
+ log($"ERROR: {e.Exception}");
+ })
.AddListenerUpdateInfo((_, e) =>
- {{
- log($"Update info: Code={{e.Info.Code}}, Versions={{e.Info.Body?.Count ?? 0}}");
- }})
+ {
+ log($"Update info: Code={e.Info.Code}, Versions={e.Info.Body?.Count ?? 0}");
+ })
.LaunchAsync();
log("Update process completed");
-}}
+}
catch (Exception ex)
-{{
- log($"FATAL: {{ex.Message}}");
+{
+ log($"FATAL: {ex.Message}");
Console.Error.WriteLine(ex);
Environment.Exit(1);
-}}
+}
""";
- private const string UpgradeTemplate = """
-#r "nuget: GeneralUpdate.Core"
-#r "nuget: GeneralUpdate.ClientCore"
-
-using GeneralUpdate.Core;
-using GeneralUpdate.Common.Shared;
-using GeneralUpdate.Common.Internal.Event;
+ private const string UpgradeCsproj = """
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+""";
-var log = (string msg) => Console.WriteLine($"[{{DateTime.Now:HH:mm:ss}}] {{msg}}");
+ private const string UpgradeProgram = """
+var log = (string msg) => Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {msg}");
try
-{{
+{
log("Upgrade process started");
log("Working directory: " + Environment.CurrentDirectory);
- await new GeneralUpdateBootstrap()
+ await new GeneralUpdate.Core.GeneralUpdateBootstrap()
.AddListenerMultiDownloadStatistics((_, e) =>
- {{
+ {
var v = e.Version as GeneralUpdate.Common.Shared.Object.VersionInfo;
- log($"Download: {{v?.Version}} {{e.ProgressPercentage}}%");
- }})
+ log($"Download: {v?.Version} {e.ProgressPercentage}%");
+ })
.AddListenerMultiAllDownloadCompleted((_, e) =>
- {{
+ {
log(e.IsAllDownloadCompleted ? "Downloads done" : "Download failed");
- }})
+ })
.AddListenerException((_, e) =>
- {{
- log($"ERROR: {{e.Exception}}");
- }})
+ {
+ log($"ERROR: {e.Exception}");
+ })
.LaunchAsync();
log("Upgrade process finished successfully");
-}}
+}
catch (Exception ex)
-{{
- log($"FATAL: {{ex.Message}}");
+{
+ log($"FATAL: {ex.Message}");
Console.Error.WriteLine(ex);
Environment.Exit(1);
-}}
+}
""";
public async Task GenerateAsync(SimulateConfigModel config, string outputDir)
{
var serverUrl = $"http://127.0.0.1:{config.ServerPort}";
- // client.cs
- var clientCode = string.Format(ClientTemplate,
- EscapeForCSharp(config.AppDirectory),
- serverUrl,
- "upgrade.cs", // AppName - the upgrade process
- "client.cs", // MainAppName
- config.CurrentVersion,
- "1.0.0.0", // upgrade client version
- config.ProductId,
- config.AppSecretKey);
-
- await File.WriteAllTextAsync(
- Path.Combine(outputDir, "client.cs"),
- clientCode,
+ // client/
+ var clientDir = Path.Combine(outputDir, "client");
+ Directory.CreateDirectory(clientDir);
+ await File.WriteAllTextAsync(Path.Combine(clientDir, "client.csproj"), ClientCsproj, Encoding.UTF8);
+ await File.WriteAllTextAsync(Path.Combine(clientDir, "Program.cs"),
+ string.Format(ClientProgram,
+ EscapeForCSharp(config.AppDirectory),
+ serverUrl,
+ "upgrade.exe", // AppName
+ "client.exe", // MainAppName
+ config.CurrentVersion,
+ "1.0.0.0", // upgrade client version
+ config.ProductId,
+ config.AppSecretKey),
Encoding.UTF8);
- // upgrade.cs
- var upgradeCode = string.Format(UpgradeTemplate,
- EscapeForCSharp(config.AppDirectory));
-
- await File.WriteAllTextAsync(
- Path.Combine(outputDir, "upgrade.cs"),
- upgradeCode,
+ // upgrade/
+ var upgradeDir = Path.Combine(outputDir, "upgrade");
+ Directory.CreateDirectory(upgradeDir);
+ await File.WriteAllTextAsync(Path.Combine(upgradeDir, "upgrade.csproj"), UpgradeCsproj, Encoding.UTF8);
+ await File.WriteAllTextAsync(Path.Combine(upgradeDir, "Program.cs"),
+ string.Format(UpgradeProgram,
+ EscapeForCSharp(config.AppDirectory)),
Encoding.UTF8);
}
diff --git a/src/Services/SimulationService.cs b/src/Services/SimulationService.cs
index 82017a1..2b70cb2 100644
--- a/src/Services/SimulationService.cs
+++ b/src/Services/SimulationService.cs
@@ -57,14 +57,14 @@ public async Task RunAsync(
config.ServerPort = _server.Port;
// 4. Generate client/upgrade scripts
- Log("STEP 4: Generating client.cs and upgrade.cs", progress);
+ Log("STEP 4: Generating client/upgrade projects", progress);
await _generator.GenerateAsync(config, config.OutputDirectory);
- Log($" client.cs → {config.OutputDirectory}", progress);
- Log($" upgrade.cs → {config.OutputDirectory}", progress);
+ Log($" client/ → {config.OutputDirectory}/client", progress);
+ Log($" upgrade/ → {config.OutputDirectory}/upgrade", progress);
- // 5. Run client
- Log("STEP 5: Running client (dotnet run client.cs)", progress);
- var clientResult = await RunDotNetScript(config.OutputDirectory, "client.cs", ct);
+ // 5. Run client via dotnet run --project
+ Log("STEP 5: Running client (dotnet run --project client)", progress);
+ var clientResult = await RunDotNetProject(Path.Combine(config.OutputDirectory, "client"), ct);
Log(clientResult.Output, progress);
if (!clientResult.Success)
@@ -137,11 +137,11 @@ private void Validate(SimulateConfigModel config)
catch { throw new InvalidOperationException("dotnet CLI not found. Install .NET 10.0 SDK."); }
}
- private async Task<(bool Success, string Output)> RunDotNetScript(string workDir, string script, CancellationToken ct)
+ private async Task<(bool Success, string Output)> RunDotNetProject(string projectDir, CancellationToken ct)
{
- var psi = new ProcessStartInfo("dotnet", $"run {script}")
+ var psi = new ProcessStartInfo("dotnet", "run --project .")
{
- WorkingDirectory = workDir,
+ WorkingDirectory = projectDir,
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = System.Text.Encoding.UTF8,