diff --git a/build/windows/finalize-install-package.sh b/build/windows/finalize-install-package.sh
index 117e33e5..8428cf41 100755
--- a/build/windows/finalize-install-package.sh
+++ b/build/windows/finalize-install-package.sh
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
+set -ex
+
##########
## Read config
##########
diff --git a/docs/technical/smapi.md b/docs/technical/smapi.md
index d115aefa..3dd66c78 100644
--- a/docs/technical/smapi.md
+++ b/docs/technical/smapi.md
@@ -32,6 +32,7 @@ argument | purpose
`--install` | Preselects the install action, skipping the prompt asking what the user wants to do.
`--uninstall` | Preselects the uninstall action, skipping the prompt asking what the user wants to do.
`--game-path "path"` | Specifies the full path to the folder containing the Stardew Valley executable, skipping automatic detection and any prompt to choose a path. If the path is not valid, the installer displays an error.
+`--headless` | Installs or Uninstalls SMAPI without any user interaction. Should only be used in scripts, tools or if you know what you're doing.
SMAPI itself recognises five arguments, but these are meant for internal use or testing, and might
change without warning. **On Linux/macOS**, command-line arguments won't work; see _environment
@@ -96,7 +97,7 @@ Windows](#on-windows)_ section below to create a build that retains the icon.**
2. Run `sudo apt update` in WSL to update the package list.
3. The rest of the instructions below should be run in WSL.
2. Install the required software:
- 1. Install the [.NET 5 SDK](https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu).
+ 1. Install the [.NET 5 SDK](https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu).
_For Ubuntu-based systems, you can run `lsb_release -a` to get the Ubuntu version number._
2. [Install Steam](https://linuxconfig.org/how-to-install-steam-on-ubuntu-20-04-focal-fossa-linux).
3. Launch `steam` and install the game like usual.
diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs
index 32a4e6e5..d07538e7 100644
--- a/src/SMAPI.Installer/InteractiveInstaller.cs
+++ b/src/SMAPI.Installer/InteractiveInstaller.cs
@@ -33,6 +33,9 @@ namespace StardewModdingApi.Installer
"SMAPI.ErrorHandler"
};
+ /// If the installer should run headless, does not ask the user for any input when true.
+ private readonly bool Headless;
+
/// Get the absolute file or folder paths to remove when uninstalling SMAPI.
/// The folder for Stardew Valley and SMAPI.
/// The folder for SMAPI mods.
@@ -97,10 +100,11 @@ namespace StardewModdingApi.Installer
*********/
/// Construct an instance.
/// The absolute path to the directory containing the files to copy into the game folder.
- public InteractiveInstaller(string bundlePath)
+ public InteractiveInstaller(string bundlePath, bool headless)
{
this.BundlePath = bundlePath;
this.ConsoleWriter = new ColorfulConsoleWriter(EnvironmentUtility.DetectPlatform());
+ this.Headless = headless;
}
/// Run the install or uninstall script.
@@ -142,14 +146,14 @@ namespace StardewModdingApi.Installer
if (context.IsUnix)
{
this.PrintError($"This is the installer for Windows. Run the 'install on {context.Platform}.{(context.Platform == Platform.Mac ? "command" : "sh")}' file instead.");
- Console.ReadLine();
+ this.AwaitConfirmation();
return;
}
#else
if (context.IsWindows)
{
this.PrintError($"This is the installer for Linux/macOS. Run the 'install on Windows.exe' file instead.");
- Console.ReadLine();
+ this.AwaitConfirmation();
return;
}
#endif
@@ -163,7 +167,12 @@ namespace StardewModdingApi.Installer
if (installArg && uninstallArg)
{
this.PrintError("You can't specify both --install and --uninstall command-line flags.");
- Console.ReadLine();
+ this.AwaitConfirmation();
+ return;
+ }
+ if (!installArg && !uninstallArg && Headless)
+ {
+ this.PrintError("Either --install or --uninstall is required when running with --headless.");
return;
}
@@ -180,7 +189,7 @@ namespace StardewModdingApi.Installer
** Step 2: choose a theme (can't auto-detect on Linux/macOS)
*********/
MonitorColorScheme scheme = MonitorColorScheme.AutoDetect;
- if (context.IsUnix)
+ if (context.IsUnix && !Headless)
{
/****
** print header
@@ -245,7 +254,7 @@ namespace StardewModdingApi.Installer
if (installDir == null)
{
this.PrintError("Failed finding your game path.");
- Console.ReadLine();
+ this.AwaitConfirmation();
return;
}
@@ -262,7 +271,7 @@ namespace StardewModdingApi.Installer
if (!File.Exists(paths.GameDllPath))
{
this.PrintError("The detected game install path doesn't contain a Stardew Valley executable.");
- Console.ReadLine();
+ this.AwaitConfirmation();
return;
}
Console.Clear();
@@ -513,7 +522,7 @@ namespace StardewModdingApi.Installer
);
}
- Console.ReadKey();
+ this.AwaitConfirmation();
}
@@ -594,7 +603,7 @@ namespace StardewModdingApi.Installer
{
this.PrintError($"Oops! The installer couldn't delete {path}: [{ex.GetType().Name}] {ex.Message}.");
this.PrintError("Try rebooting your computer and then run the installer again. If that doesn't work, try deleting it yourself then press any key to retry.");
- Console.ReadKey();
+ this.AwaitConfirmation();
}
}
}
@@ -906,5 +915,14 @@ namespace StardewModdingApi.Installer
_ => true
};
}
+
+ /// Await confirmation (pressing enter) from the User.
+ private void AwaitConfirmation()
+ {
+ if (!this.Headless)
+ {
+ Console.ReadLine();
+ }
+ }
}
}
diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs
index dc452a46..cf38f1cf 100644
--- a/src/SMAPI.Installer/Program.cs
+++ b/src/SMAPI.Installer/Program.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Threading;
+using System.Linq;
namespace StardewModdingApi.Installer
{
@@ -47,8 +48,9 @@ namespace StardewModdingApi.Installer
// set up assembly resolution
AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve;
+ var headless = args.Contains("--headless");
// launch installer
- var installer = new InteractiveInstaller(bundleDir.FullName);
+ var installer = new InteractiveInstaller(bundleDir.FullName, headless);
try
{