diff --git a/LANCommander.Launcher/LANCommander.Launcher.csproj b/LANCommander.Launcher/LANCommander.Launcher.csproj
index 3a552aca..360068ba 100644
--- a/LANCommander.Launcher/LANCommander.Launcher.csproj
+++ b/LANCommander.Launcher/LANCommander.Launcher.csproj
@@ -27,6 +27,7 @@
+
diff --git a/LANCommander.Launcher/UI/Components/PowerShellConsole.razor b/LANCommander.Launcher/UI/Components/PowerShellConsole.razor
new file mode 100644
index 00000000..0177fa5f
--- /dev/null
+++ b/LANCommander.Launcher/UI/Components/PowerShellConsole.razor
@@ -0,0 +1,158 @@
+@using XtermBlazor
+@inject SDK.Client Client
+
+
+
+
+@code {
+ private Xterm Terminal;
+ private TaskCompletionSource InputTaskCompletionSource;
+
+ private string Command { get; set; } = "";
+ private int Position { get; set; } = 0;
+ private int Columns { get; set; } = 0;
+ private int Rows { get; set; } = 0;
+
+ private TerminalOptions _options = new TerminalOptions
+ {
+ CursorBlink = true,
+ CursorStyle = CursorStyle.Bar,
+ Theme =
+ {
+ Background = "#17615e",
+ },
+
+ };
+
+ protected override async Task OnInitializedAsync()
+ {
+ Client.Scripts.OnDebug = async (ps) =>
+ {
+ while (true)
+ {
+ InputTaskCompletionSource = new TaskCompletionSource();
+
+ await InputTaskCompletionSource.Task;
+
+ await ps.InvokeAsync();
+ }
+ };
+ }
+
+ private async Task OnFirstRender()
+ {
+ Columns = await Terminal.GetColumns();
+ Rows = await Terminal.GetRows();
+ }
+
+ private async Task OnResize(ResizeEventArgs args)
+ {
+ Columns = args.Columns;
+ Rows = args.Rows;
+ }
+
+ private async Task OnData(string data)
+ {
+ var code = System.Text.Encoding.UTF8.GetBytes(data)[0];
+
+ switch (code)
+ {
+ case 13:
+ await Terminal.Write("\r\n");
+ await Terminal.WriteLine($"Output: {Command}");
+ Position = 0;
+ Command = "";
+ break;
+
+ case 8:
+ case 127:
+ await Backspace();
+ break;
+
+ case 27:
+ switch (data.Substring(1))
+ {
+ case "[C":
+ await CursorRight();
+ break;
+
+ case "[D":
+ await CursorLeft();
+ break;
+ }
+ break;
+
+ case < 32:
+ case > 127:
+ return;
+
+ default:
+ Command += data;
+ await Key(data);
+ break;
+ }
+ }
+
+ private async Task Key(string key)
+ {
+ Position++;
+ await Terminal.Write(key);
+ }
+
+ private async Task Backspace()
+ {
+ var originalPosition = Position;
+
+ if (originalPosition > 0)
+ {
+ // If at end of command
+ if (originalPosition == Command.Length)
+ {
+ await Terminal.Write("\x1b[D \x1b[D");
+
+ Command = Command.Substring(0, Command.Length - 1);
+ Position--;
+ }
+ else
+ {
+ var tail = Command.Substring(Position);
+
+ await Terminal.Write("\x1b[D");
+ await Terminal.Write(tail + " ");
+
+ for (int i = 0; i < tail.Length + 1; i++)
+ {
+ await Terminal.Write("\x1b[D");
+ }
+
+ Position--;
+
+ Command = Command.Substring(0, Position) + tail;
+ }
+ }
+ }
+
+ private async Task CursorLeft(int count = 1)
+ {
+ for (var i = 0; i < count; i++)
+ {
+ if (Position > 0)
+ {
+ Position--;
+ await Terminal.Write("\x1b[D");
+ }
+ }
+ }
+
+ private async Task CursorRight(int count = 1)
+ {
+ for (var i = 0; i < count; i++)
+ {
+ if (Position < Columns && Position < Command.Length)
+ {
+ Position++;
+ await Terminal.Write("\x1b[C");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/LANCommander.Launcher/UI/MainLayout.razor b/LANCommander.Launcher/UI/MainLayout.razor
index e66a7691..471c4a29 100644
--- a/LANCommander.Launcher/UI/MainLayout.razor
+++ b/LANCommander.Launcher/UI/MainLayout.razor
@@ -66,6 +66,11 @@
@Body
+ @if (Settings.Debug.EnableScriptDebugging)
+ {
+
+ }
+
diff --git a/LANCommander.Launcher/wwwroot/index.html b/LANCommander.Launcher/wwwroot/index.html
index 0be77d07..d05e26e4 100644
--- a/LANCommander.Launcher/wwwroot/index.html
+++ b/LANCommander.Launcher/wwwroot/index.html
@@ -5,6 +5,7 @@
LANCommander
+
@@ -26,6 +27,7 @@
+
diff --git a/LANCommander.SDK/PowerShell/PowerShellScript.cs b/LANCommander.SDK/PowerShell/PowerShellScript.cs
index 8fd42485..1ad3efb9 100644
--- a/LANCommander.SDK/PowerShell/PowerShellScript.cs
+++ b/LANCommander.SDK/PowerShell/PowerShellScript.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -30,6 +31,10 @@ namespace LANCommander.SDK.PowerShell
private InitialSessionState InitialSessionState { get; set; }
+ private TaskCompletionSource Input { get; set; }
+
+ public Func OnDebug;
+
public PowerShellScript(ScriptType type)
{
Type = type;
@@ -179,6 +184,9 @@ namespace LANCommander.SDK.PowerShell
ps.AddScript(scriptBuilder.ToString());
var results = await ps.InvokeAsync();
+
+ if (Debug)
+ await OnDebug?.Invoke(ps);
}
}
diff --git a/LANCommander.SDK/ScriptService.cs b/LANCommander.SDK/ScriptService.cs
index 4a813d59..dbb0bcc7 100644
--- a/LANCommander.SDK/ScriptService.cs
+++ b/LANCommander.SDK/ScriptService.cs
@@ -22,6 +22,8 @@ namespace LANCommander.SDK
public delegate Task ExternalScriptRunnerHandler(PowerShellScript script);
public event ExternalScriptRunnerHandler ExternalScriptRunner;
+ public Func OnDebug;
+
public ScriptService(Client client)
{
Client = client;
@@ -54,7 +56,10 @@ namespace LANCommander.SDK
script.UseFile(ScriptHelper.GetScriptFilePath(installDirectory, gameId, Enums.ScriptType.Install));
if (debug)
+ {
script.EnableDebug();
+ script.OnDebug = OnDebug;
+ }
bool handled = false;
@@ -95,7 +100,10 @@ namespace LANCommander.SDK
script.UseFile(path);
if (debug)
+ {
script.EnableDebug();
+ script.OnDebug = OnDebug;
+ }
bool handled = false;
@@ -136,7 +144,10 @@ namespace LANCommander.SDK
script.UseFile(path);
if (debug)
+ {
script.EnableDebug();
+ script.OnDebug = OnDebug;
+ }
bool handled = false;
@@ -174,7 +185,10 @@ namespace LANCommander.SDK
script.UseFile(path);
if (debug)
+ {
script.EnableDebug();
+ script.OnDebug = OnDebug;
+ }
bool handled = false;
@@ -223,7 +237,10 @@ namespace LANCommander.SDK
SDK.GameService.UpdatePlayerAlias(installDirectory, gameId, newName);
if (debug)
+ {
script.EnableDebug();
+ script.OnDebug = OnDebug;
+ }
bool handled = false;
@@ -266,7 +283,10 @@ namespace LANCommander.SDK
GameService.UpdateCurrentKey(installDirectory, gameId, key);
if (debug)
+ {
script.EnableDebug();
+ script.OnDebug = OnDebug;
+ }
bool handled = false;