mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-06 17:10:13 +00:00
Limit ASF to a single instance per directory
This commit is contained in:
9
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
9
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
@@ -963,6 +963,15 @@ namespace ArchiSteamFarm.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu ASF process is already running for this working directory, aborting!.
|
||||
/// </summary>
|
||||
public static string ErrorSingleInstanceRequired {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorSingleInstanceRequired", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Could not check latest version!.
|
||||
/// </summary>
|
||||
|
||||
@@ -717,4 +717,7 @@ StackTrace:
|
||||
<value>Bot has {0} games remaining in its background queue.</value>
|
||||
<comment>{0} will be replaced by remaining number of games in BGR's queue</comment>
|
||||
</data>
|
||||
<data name="ErrorSingleInstanceRequired" xml:space="preserve">
|
||||
<value>ASF process is already running for this working directory, aborting!</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -139,7 +139,7 @@ namespace ArchiSteamFarm.NLog {
|
||||
return !string.IsNullOrEmpty(result) ? result.Trim() : null;
|
||||
}
|
||||
|
||||
internal static void InitCoreLoggers() {
|
||||
internal static void InitCoreLoggers(bool uniqueInstance) {
|
||||
if (LogManager.Configuration != null) {
|
||||
IsUsingCustomConfiguration = true;
|
||||
InitConsoleLoggers();
|
||||
@@ -156,14 +156,18 @@ namespace ArchiSteamFarm.NLog {
|
||||
config.AddTarget(coloredConsoleTarget);
|
||||
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, coloredConsoleTarget));
|
||||
|
||||
FileTarget fileTarget = new FileTarget("File") {
|
||||
DeleteOldFileOnStartup = true,
|
||||
FileName = SharedInfo.LogFile,
|
||||
Layout = GeneralLayout
|
||||
};
|
||||
if (uniqueInstance) {
|
||||
FileTarget fileTarget = new FileTarget("File") {
|
||||
CleanupFileName = false,
|
||||
ConcurrentWrites = false,
|
||||
DeleteOldFileOnStartup = true,
|
||||
FileName = SharedInfo.LogFile,
|
||||
Layout = GeneralLayout
|
||||
};
|
||||
|
||||
config.AddTarget(fileTarget);
|
||||
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
|
||||
config.AddTarget(fileTarget);
|
||||
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
|
||||
}
|
||||
|
||||
LogManager.Configuration = config;
|
||||
InitConsoleLoggers();
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using ArchiSteamFarm.Localization;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
@@ -33,6 +35,8 @@ namespace ArchiSteamFarm {
|
||||
[NotNull]
|
||||
internal static string Variant => RuntimeInformation.OSDescription.Trim();
|
||||
|
||||
private static Mutex SingleInstance;
|
||||
|
||||
internal static void Init(bool systemRequired, GlobalConfig.EOptimizationMode optimizationMode) {
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||
DisableQuickEditMode();
|
||||
@@ -60,6 +64,24 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool RegisterProcess() {
|
||||
if (SingleInstance != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string uniqueName = "Global\\" + SharedInfo.AssemblyName + "-" + Convert.ToBase64String(Encoding.UTF8.GetBytes(Directory.GetCurrentDirectory()));
|
||||
|
||||
Mutex singleInstance = new Mutex(true, uniqueName, out bool result);
|
||||
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SingleInstance = singleInstance;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void UnixSetFileAccessExecutable(string path) {
|
||||
if (string.IsNullOrEmpty(path) || !File.Exists(path)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(path));
|
||||
@@ -73,6 +95,16 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
internal static void UnregisterProcess() {
|
||||
if (SingleInstance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SingleInstance.ReleaseMutex();
|
||||
SingleInstance.Dispose();
|
||||
SingleInstance = null;
|
||||
}
|
||||
|
||||
private static void DisableQuickEditMode() {
|
||||
if (Console.IsOutputRedirected) {
|
||||
return;
|
||||
|
||||
@@ -118,7 +118,12 @@ namespace ArchiSteamFarm {
|
||||
Target.Register<HistoryTarget>(HistoryTarget.TargetName);
|
||||
Target.Register<SteamTarget>(SteamTarget.TargetName);
|
||||
|
||||
InitCore(args);
|
||||
if (!await InitCore(args).ConfigureAwait(false)) {
|
||||
await Exit(1).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await InitASF(args).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -141,7 +146,7 @@ namespace ArchiSteamFarm {
|
||||
await ASF.Init().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static void InitCore(IReadOnlyCollection<string> args) {
|
||||
private static async Task<bool> InitCore(IReadOnlyCollection<string> args) {
|
||||
Directory.SetCurrentDirectory(SharedInfo.HomeDirectory);
|
||||
|
||||
// Allow loading configs from source tree if it's a debug build
|
||||
@@ -166,7 +171,17 @@ namespace ArchiSteamFarm {
|
||||
ParsePreInitArgs(args);
|
||||
}
|
||||
|
||||
Logging.InitCoreLoggers();
|
||||
bool uniqueInstance = OS.RegisterProcess();
|
||||
Logging.InitCoreLoggers(uniqueInstance);
|
||||
|
||||
if (!uniqueInstance) {
|
||||
ASF.ArchiLogger.LogGenericError(Strings.ErrorSingleInstanceRequired);
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static async Task InitGlobalConfigAndLanguage() {
|
||||
@@ -320,6 +335,7 @@ namespace ArchiSteamFarm {
|
||||
// Ensure that IPC is stopped before we finalize shutdown sequence
|
||||
await ArchiKestrel.Stop().ConfigureAwait(false);
|
||||
|
||||
// Stop all the active bots so they can disconnect cleanly
|
||||
if (Bot.Bots?.Count > 0) {
|
||||
// Stop() function can block due to SK2 sockets, don't forget a maximum delay
|
||||
await Task.WhenAny(Utilities.InParallel(Bot.Bots.Values.Select(bot => Task.Run(() => bot.Stop(true)))), Task.Delay(Bot.Bots.Count * WebBrowser.MaxTries * 1000)).ConfigureAwait(false);
|
||||
@@ -328,8 +344,12 @@ namespace ArchiSteamFarm {
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Flush all the pending writes to log files
|
||||
LogManager.Flush();
|
||||
|
||||
// Unregister the process from single instancing
|
||||
OS.UnregisterProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user