diff --git a/src/Tgstation.Server.Host/Core/SetupWizard.cs b/src/Tgstation.Server.Host/Core/SetupWizard.cs
index bc3a0759b8..dff6446387 100644
--- a/src/Tgstation.Server.Host/Core/SetupWizard.cs
+++ b/src/Tgstation.Server.Host/Core/SetupWizard.cs
@@ -638,41 +638,60 @@ namespace Tgstation.Server.Host.Core
}
var userConfigFileName = String.Format(CultureInfo.InvariantCulture, "appsettings.{0}.json", hostingEnvironment.EnvironmentName);
- var exists = await ioManager.FileExists(userConfigFileName, cancellationToken).ConfigureAwait(false);
- bool shouldRunBasedOnAutodetect;
- if (exists)
+ async Task HandleSetupCancel()
{
- var bytes = await ioManager.ReadAllBytes(userConfigFileName, cancellationToken).ConfigureAwait(false);
- var contents = Encoding.UTF8.GetString(bytes);
- var existingConfigIsEmpty = String.IsNullOrWhiteSpace(contents) || contents.Trim() == "{}";
- logger.LogTrace("Configuration json detected. Empty: {0}", existingConfigIsEmpty);
- shouldRunBasedOnAutodetect = existingConfigIsEmpty;
- }
- else
- {
- shouldRunBasedOnAutodetect = true;
- logger.LogTrace("No configuration json detected");
+ await console.WriteAsync(String.Empty, true, default).ConfigureAwait(false);
+ await console.WriteAsync("Aborting setup!", true, default).ConfigureAwait(false);
}
- if (!shouldRunBasedOnAutodetect)
- {
- if (forceRun)
+ // Link passed cancellationToken with cancel key press
+ Task finalTask = Task.CompletedTask;
+ using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, console.CancelKeyPress))
+ using ((cancellationToken = cts.Token).Register(() => finalTask = HandleSetupCancel()))
+ try
{
- logger.LogTrace("Asking user to bypass due to force run request...");
- await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "The configuration settings are requesting the setup wizard be run, but you already appear to have a configuration file ({0})!", userConfigFileName), true, cancellationToken).ConfigureAwait(false);
+ var exists = await ioManager.FileExists(userConfigFileName, cancellationToken).ConfigureAwait(false);
- forceRun = await PromptYesNo("Continue running setup wizard? (y/n): ", cancellationToken).ConfigureAwait(false);
+ bool shouldRunBasedOnAutodetect;
+ if (exists)
+ {
+ var bytes = await ioManager.ReadAllBytes(userConfigFileName, cancellationToken).ConfigureAwait(false);
+ var contents = Encoding.UTF8.GetString(bytes);
+ var existingConfigIsEmpty = String.IsNullOrWhiteSpace(contents) || contents.Trim() == "{}";
+ logger.LogTrace("Configuration json detected. Empty: {0}", existingConfigIsEmpty);
+ shouldRunBasedOnAutodetect = existingConfigIsEmpty;
+ }
+ else
+ {
+ shouldRunBasedOnAutodetect = true;
+ logger.LogTrace("No configuration json detected");
+ }
+
+ if (!shouldRunBasedOnAutodetect)
+ {
+ if (forceRun)
+ {
+ logger.LogTrace("Asking user to bypass due to force run request...");
+ await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "The configuration settings are requesting the setup wizard be run, but you already appear to have a configuration file ({0})!", userConfigFileName), true, cancellationToken).ConfigureAwait(false);
+
+ forceRun = await PromptYesNo("Continue running setup wizard? (y/n): ", cancellationToken).ConfigureAwait(false);
+ }
+
+ if (!forceRun)
+ return false;
+ }
+
+ // flush the logs to prevent console conflicts
+ await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
+
+ await RunWizard(userConfigFileName, cancellationToken).ConfigureAwait(false);
+ }
+ finally
+ {
+ await finalTask.ConfigureAwait(false);
}
- if (!forceRun)
- return false;
- }
-
- // flush the logs to prevent console conflicts
- await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
-
- await RunWizard(userConfigFileName, cancellationToken).ConfigureAwait(false);
return true;
}
}
diff --git a/src/Tgstation.Server.Host/IO/Console.cs b/src/Tgstation.Server.Host/IO/Console.cs
index 9f1fceba80..0d90d54c25 100644
--- a/src/Tgstation.Server.Host/IO/Console.cs
+++ b/src/Tgstation.Server.Host/IO/Console.cs
@@ -6,11 +6,50 @@ using System.Threading.Tasks;
namespace Tgstation.Server.Host.IO
{
///
- sealed class Console : IConsole
+ sealed class Console : IConsole, IDisposable
{
///
public bool Available => Environment.UserInteractive;
+ ///
+ public CancellationToken CancelKeyPress => cancelKeyCts.Token;
+
+ ///
+ /// The for .
+ ///
+ readonly CancellationTokenSource cancelKeyCts;
+
+ ///
+ /// If the was disposed;
+ ///
+ bool disposed;
+
+ ///
+ /// Initializes a new instance of the .
+ ///
+ public Console()
+ {
+ cancelKeyCts = new CancellationTokenSource();
+ System.Console.CancelKeyPress += (sender, e) =>
+ {
+ lock (cancelKeyCts)
+ {
+ if (!disposed)
+ cancelKeyCts.Cancel();
+ }
+ };
+ }
+
+ ///
+ public void Dispose()
+ {
+ lock (cancelKeyCts)
+ {
+ cancelKeyCts.Dispose();
+ disposed = true;
+ }
+ }
+
void CheckAvailable()
{
if (!Available)
diff --git a/src/Tgstation.Server.Host/IO/IConsole.cs b/src/Tgstation.Server.Host/IO/IConsole.cs
index 119b19d5dc..405ffb425b 100644
--- a/src/Tgstation.Server.Host/IO/IConsole.cs
+++ b/src/Tgstation.Server.Host/IO/IConsole.cs
@@ -13,6 +13,11 @@ namespace Tgstation.Server.Host.IO
///
bool Available { get; }
+ ///
+ /// Gets a that triggers if Crtl+C or an equivalent is pressed.
+ ///
+ CancellationToken CancelKeyPress { get; }
+
///
/// Write some to the
///