mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-06 17:10:13 +00:00
Improve runtime compatibility
This commit does 3 things: - adds safeguard against running generic-netf in unsupported environments - adds notice about providing ASF with unknown command-line arguments - refactors old pre+post args parsing into a single window
This commit is contained in:
396
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
396
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -736,4 +736,10 @@ Process uptime: {1}</value>
|
||||
<value>Result: {0}</value>
|
||||
<comment>{0} will be replaced by generic result of various functions that use this string</comment>
|
||||
</data>
|
||||
<data name="WarningUnsupportedEnvironment" xml:space="preserve">
|
||||
<value>You're attempting to run {0} variant of ASF in unsupported environment: {1}. Supply --ignore-unsupported-environment argument if you really know what you're doing.</value>
|
||||
</data>
|
||||
<data name="WarningUnknownCommandLineArgument" xml:space="preserve">
|
||||
<value>Unknown command-line argument: {0}</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -40,8 +40,13 @@ namespace ArchiSteamFarm {
|
||||
|
||||
private static Mutex? SingleInstance;
|
||||
|
||||
internal static void CoreInit() {
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Console.IsOutputRedirected) {
|
||||
internal static void CoreInit(bool systemRequired) {
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||
if (systemRequired) {
|
||||
WindowsKeepSystemActive();
|
||||
}
|
||||
|
||||
if (!Console.IsOutputRedirected) {
|
||||
// Normally we should use UTF-8 encoding as it's the most correct one for our case, and we already use it on other OSes such as Linux
|
||||
// However, older Windows versions, mainly 7/8.1 can't into UTF-8 without appropriate console font, and expecting from users to change it manually is unwanted
|
||||
// As irrational as it can sound, those versions actually can work with unicode encoding instead, as they magically map it into proper chars despite of incorrect font
|
||||
@@ -56,6 +61,7 @@ namespace ArchiSteamFarm {
|
||||
WindowsDisableQuickEditMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static ICrossProcessSemaphore CreateCrossProcessSemaphore(string objectName) {
|
||||
if (string.IsNullOrEmpty(objectName)) {
|
||||
@@ -67,15 +73,39 @@ namespace ArchiSteamFarm {
|
||||
return new CrossProcessFileBasedSemaphore(resourceName);
|
||||
}
|
||||
|
||||
internal static void Init(bool systemRequired, GlobalConfig.EOptimizationMode optimizationMode) {
|
||||
if (!Enum.IsDefined(typeof(GlobalConfig.EOptimizationMode), optimizationMode)) {
|
||||
throw new ArgumentNullException(nameof(optimizationMode));
|
||||
internal static bool VerifyEnvironment() {
|
||||
#if NETFRAMEWORK
|
||||
// This is .NET Framework build, we support that one only on mono for platforms not supported by .NET Core
|
||||
|
||||
// We're not going to analyze source builds, as we don't know what changes the author has made, assume they have a point
|
||||
if (SharedInfo.BuildInfo.IsCustomBuild) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||
if (systemRequired) {
|
||||
WindowsKeepSystemActive();
|
||||
// All windows variants have valid .NET Core build, and generic-netf is supported only on mono
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !RuntimeCompatibility.IsRunningOnMono) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return RuntimeInformation.OSArchitecture switch {
|
||||
// Sadly we can't tell a difference between ARMv6 and ARMv7 reliably, we'll believe that this linux-arm user knows what he's doing and he's indeed in need of generic-netf on ARMv6
|
||||
Architecture.Arm => true,
|
||||
|
||||
// Apart from real x86, this also covers all unknown architectures, such as sparc, ppc64, and anything else Mono might support, we're fine with that
|
||||
Architecture.X86 => true,
|
||||
|
||||
// Everything else is covered by .NET Core
|
||||
_ => false
|
||||
};
|
||||
#else
|
||||
// This is .NET Core build, we support all scenarios
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void Init(GlobalConfig.EOptimizationMode optimizationMode) {
|
||||
if (!Enum.IsDefined(typeof(GlobalConfig.EOptimizationMode), optimizationMode)) {
|
||||
throw new ArgumentNullException(nameof(optimizationMode));
|
||||
}
|
||||
|
||||
switch (optimizationMode) {
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
private static readonly TaskCompletionSource<byte> ShutdownResetEvent = new();
|
||||
|
||||
private static bool IgnoreUnsupportedEnvironment;
|
||||
private static bool SystemRequired;
|
||||
|
||||
internal static async Task Exit(byte exitCode = 0) {
|
||||
@@ -119,38 +120,26 @@ namespace ArchiSteamFarm {
|
||||
Target.Register<HistoryTarget>(HistoryTarget.TargetName);
|
||||
Target.Register<SteamTarget>(SteamTarget.TargetName);
|
||||
|
||||
if (!await InitCore(args).ConfigureAwait(false)) {
|
||||
if (!await InitCore(args).ConfigureAwait(false) || !await InitASF().ConfigureAwait(false)) {
|
||||
await Exit(1).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await InitASF(args).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static async Task InitASF(IReadOnlyCollection<string>? args) {
|
||||
OS.CoreInit();
|
||||
|
||||
Console.Title = SharedInfo.ProgramIdentifier;
|
||||
ASF.ArchiLogger.LogGenericInfo(SharedInfo.ProgramIdentifier);
|
||||
|
||||
private static async Task<bool> InitASF() {
|
||||
if (!await InitGlobalConfigAndLanguage().ConfigureAwait(false)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ASF.GlobalConfig == null) {
|
||||
throw new InvalidOperationException(nameof(ASF.GlobalConfig));
|
||||
}
|
||||
|
||||
// Parse post-init args
|
||||
if (args != null) {
|
||||
ParsePostInitArgs(args);
|
||||
}
|
||||
|
||||
OS.Init(SystemRequired, ASF.GlobalConfig.OptimizationMode);
|
||||
OS.Init(ASF.GlobalConfig.OptimizationMode);
|
||||
|
||||
await InitGlobalDatabaseAndServices().ConfigureAwait(false);
|
||||
await ASF.Init().ConfigureAwait(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static async Task<bool> InitCore(IReadOnlyCollection<string>? args) {
|
||||
@@ -173,9 +162,9 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse pre-init args
|
||||
// Parse args
|
||||
if (args != null) {
|
||||
ParsePreInitArgs(args);
|
||||
ParseArgs(args);
|
||||
}
|
||||
|
||||
bool uniqueInstance = OS.RegisterProcess();
|
||||
@@ -188,6 +177,20 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
OS.CoreInit(SystemRequired);
|
||||
|
||||
Console.Title = SharedInfo.ProgramIdentifier;
|
||||
ASF.ArchiLogger.LogGenericInfo(SharedInfo.ProgramIdentifier);
|
||||
|
||||
if (!IgnoreUnsupportedEnvironment) {
|
||||
if (!OS.VerifyEnvironment()) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnsupportedEnvironment, SharedInfo.BuildInfo.Variant, OS.Variant));
|
||||
await Task.Delay(10000).ConfigureAwait(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -413,7 +416,7 @@ namespace ArchiSteamFarm {
|
||||
e.SetObserved();
|
||||
}
|
||||
|
||||
private static void ParsePostInitArgs(IReadOnlyCollection<string> args) {
|
||||
private static void ParseArgs(IReadOnlyCollection<string> args) {
|
||||
if (args == null) {
|
||||
throw new ArgumentNullException(nameof(args));
|
||||
}
|
||||
@@ -424,49 +427,7 @@ namespace ArchiSteamFarm {
|
||||
if (!string.IsNullOrEmpty(envCryptKey)) {
|
||||
HandleCryptKeyArgument(envCryptKey!);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
}
|
||||
|
||||
bool cryptKeyNext = false;
|
||||
|
||||
foreach (string arg in args) {
|
||||
switch (arg) {
|
||||
case "--cryptkey" when !cryptKeyNext:
|
||||
cryptKeyNext = true;
|
||||
|
||||
break;
|
||||
case "--no-restart" when !cryptKeyNext:
|
||||
RestartAllowed = false;
|
||||
|
||||
break;
|
||||
case "--process-required" when !cryptKeyNext:
|
||||
ProcessRequired = true;
|
||||
|
||||
break;
|
||||
case "--system-required" when !cryptKeyNext:
|
||||
SystemRequired = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
if (cryptKeyNext) {
|
||||
cryptKeyNext = false;
|
||||
HandleCryptKeyArgument(arg);
|
||||
} else if ((arg.Length > 11) && arg.StartsWith("--cryptkey=", StringComparison.Ordinal)) {
|
||||
HandleCryptKeyArgument(arg.Substring(11));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParsePreInitArgs(IReadOnlyCollection<string> args) {
|
||||
if (args == null) {
|
||||
throw new ArgumentNullException(nameof(args));
|
||||
}
|
||||
|
||||
try {
|
||||
string? envNetworkGroup = Environment.GetEnvironmentVariable(SharedInfo.EnvironmentVariableNetworkGroup);
|
||||
|
||||
if (!string.IsNullOrEmpty(envNetworkGroup)) {
|
||||
@@ -482,21 +443,45 @@ namespace ArchiSteamFarm {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
}
|
||||
|
||||
bool cryptKeyNext = false;
|
||||
bool networkGroupNext = false;
|
||||
bool pathNext = false;
|
||||
|
||||
foreach (string arg in args) {
|
||||
switch (arg) {
|
||||
case "--network-group" when !networkGroupNext && !pathNext:
|
||||
case "--cryptkey" when !cryptKeyNext && !networkGroupNext && !pathNext:
|
||||
cryptKeyNext = true;
|
||||
|
||||
break;
|
||||
case "--ignore-unsupported-environment" when !cryptKeyNext && !networkGroupNext && !pathNext:
|
||||
IgnoreUnsupportedEnvironment = true;
|
||||
|
||||
break;
|
||||
case "--network-group" when !cryptKeyNext && !networkGroupNext && !pathNext:
|
||||
networkGroupNext = true;
|
||||
|
||||
break;
|
||||
case "--path" when !networkGroupNext && !pathNext:
|
||||
case "--no-restart" when !cryptKeyNext && !networkGroupNext && !pathNext:
|
||||
RestartAllowed = false;
|
||||
|
||||
break;
|
||||
case "--process-required" when !cryptKeyNext && !networkGroupNext && !pathNext:
|
||||
ProcessRequired = true;
|
||||
|
||||
break;
|
||||
case "--path" when !cryptKeyNext && !networkGroupNext && !pathNext:
|
||||
pathNext = true;
|
||||
|
||||
break;
|
||||
case "--system-required" when !cryptKeyNext && !networkGroupNext && !pathNext:
|
||||
SystemRequired = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
if (networkGroupNext) {
|
||||
if (cryptKeyNext) {
|
||||
cryptKeyNext = false;
|
||||
HandleCryptKeyArgument(arg);
|
||||
} else if (networkGroupNext) {
|
||||
networkGroupNext = false;
|
||||
HandleNetworkGroupArgument(arg);
|
||||
} else if (pathNext) {
|
||||
@@ -507,10 +492,18 @@ namespace ArchiSteamFarm {
|
||||
case > 16 when arg.StartsWith("--network-group=", StringComparison.Ordinal):
|
||||
HandleNetworkGroupArgument(arg.Substring(16));
|
||||
|
||||
break;
|
||||
case > 11 when arg.StartsWith("--cryptkey=", StringComparison.Ordinal):
|
||||
HandleCryptKeyArgument(arg.Substring(11));
|
||||
|
||||
break;
|
||||
case > 7 when arg.StartsWith("--path=", StringComparison.Ordinal):
|
||||
HandlePathArgument(arg.Substring(7));
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownCommandLineArgument, arg));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user