mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-26 15:38:45 -07:00
446a23da2b
Initial v0.1 (commit df9dac0) used PhotinoNET wrapping WebView2 + HTML/JS,
but rendered as a blank window on first run — WebView2 + file:// URI
quirks. Switching to native WPF: built into the .NET 9 Windows SDK
(no NuGet), single-file self-contained publish, instant window open.
All Backend/*.cs orchestration logic carried over unchanged (they're
UI-framework-agnostic). Replaced:
- Program.cs (PhotinoNET bootstrap) -> App.xaml(.cs) + MainWindow.xaml(.cs)
- ui/index.html + style.css + app.js -> MainWindow.xaml (XAML views) +
App.xaml resource styles
- Backend/MessageBridge.cs (JS<->C# router) -> direct method calls in
MainWindow.xaml.cs code-behind
RecRoomPicker now uses Microsoft.Win32.OpenFolderDialog (added in .NET 8)
instead of WinForms FolderBrowserDialog — keeps the project WPF-only.
Backend files needed explicit 'using System.IO;' since the WPF SDK
doesn't include it in implicit usings.
73 lines
2.8 KiB
C#
73 lines
2.8 KiB
C#
using System.IO;
|
|
using System.Diagnostics;
|
|
|
|
namespace DorkNet.Launcher.Backend;
|
|
|
|
/// <summary>Invokes the per-version branch's <c>install-plugin.ps1</c>
|
|
/// (or <c>install-legacy-client.ps1</c> as a fallback) on the user's
|
|
/// Rec Room install. The patcher zip is unpacked by
|
|
/// <see cref="ReleaseDownloader.EnsurePatcherAsync"/> first; we just
|
|
/// run the script from inside that unpacked tree.</summary>
|
|
public sealed class ClientPatcher
|
|
{
|
|
public async Task<PatchResult> ApplyAsync(
|
|
string patcherDir,
|
|
string recRoomPath,
|
|
string photonAppId,
|
|
string photonVoiceAppId,
|
|
string apexHost,
|
|
CancellationToken ct = default)
|
|
{
|
|
var script = Path.Combine(patcherDir, "install-plugin.ps1");
|
|
if (!File.Exists(script))
|
|
{
|
|
// Some branches may ship only the legacy installer.
|
|
script = Path.Combine(patcherDir, "install-legacy-client.ps1");
|
|
if (!File.Exists(script))
|
|
{
|
|
return PatchResult.Failure(
|
|
"Patcher zip is missing install-plugin.ps1 and install-legacy-client.ps1. " +
|
|
"Open an issue with the version key + the contents of " +
|
|
$"{patcherDir}.");
|
|
}
|
|
}
|
|
|
|
var psi = new ProcessStartInfo
|
|
{
|
|
FileName = "powershell.exe",
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
WorkingDirectory = patcherDir,
|
|
};
|
|
psi.ArgumentList.Add("-NoProfile");
|
|
psi.ArgumentList.Add("-ExecutionPolicy"); psi.ArgumentList.Add("Bypass");
|
|
psi.ArgumentList.Add("-File"); psi.ArgumentList.Add(script);
|
|
psi.ArgumentList.Add("-RecRoomPath"); psi.ArgumentList.Add(recRoomPath);
|
|
psi.ArgumentList.Add("-PhotonAppId"); psi.ArgumentList.Add(photonAppId);
|
|
psi.ArgumentList.Add("-PhotonVoiceAppId");
|
|
psi.ArgumentList.Add(string.IsNullOrEmpty(photonVoiceAppId) ? photonAppId : photonVoiceAppId);
|
|
if (!string.IsNullOrEmpty(apexHost))
|
|
{
|
|
psi.ArgumentList.Add("-ServerHost"); psi.ArgumentList.Add(apexHost);
|
|
}
|
|
|
|
using var p = Process.Start(psi)
|
|
?? throw new InvalidOperationException("Failed to spawn powershell.exe");
|
|
var stdout = await p.StandardOutput.ReadToEndAsync(ct);
|
|
var stderr = await p.StandardError.ReadToEndAsync(ct);
|
|
await p.WaitForExitAsync(ct);
|
|
|
|
return p.ExitCode == 0
|
|
? PatchResult.Success(stdout)
|
|
: PatchResult.Failure(string.IsNullOrEmpty(stderr) ? stdout : stderr);
|
|
}
|
|
}
|
|
|
|
public sealed record PatchResult(bool Ok, string Log)
|
|
{
|
|
public static PatchResult Success(string log) => new(true, log);
|
|
public static PatchResult Failure(string log) => new(false, log);
|
|
}
|