diff --git a/ArchiSteamFarm/ArchiSteamFarm.csproj b/ArchiSteamFarm/ArchiSteamFarm.csproj index d1c021a77..8e8841669 100644 --- a/ArchiSteamFarm/ArchiSteamFarm.csproj +++ b/ArchiSteamFarm/ArchiSteamFarm.csproj @@ -81,6 +81,10 @@ ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll True + + ..\packages\NLog.4.4.0-beta13\lib\net45\NLog.dll + True + ..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll True @@ -90,13 +94,18 @@ True + + + + + diff --git a/ArchiSteamFarm/Logging.cs b/ArchiSteamFarm/Logging.cs index 613fc5b47..8927ee2ff 100644 --- a/ArchiSteamFarm/Logging.cs +++ b/ArchiSteamFarm/Logging.cs @@ -25,43 +25,61 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.IO; using System.Runtime.CompilerServices; +using NLog; +using NLog.Config; +using NLog.Targets; namespace ArchiSteamFarm { internal static class Logging { - private static readonly object FileLock = new object(); + private const string Layout = @"${date:format=yyyy-MM-dd HH\:mm\:ss}|${level:uppercase=true}|${message}${onexception:inner= ${exception:format=toString,Data}}"; - private static bool LogToFile; + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); internal static void Init() { - LogToFile = Program.GlobalConfig.LogToFile; + LoggingConfiguration config = new LoggingConfiguration(); - if (!LogToFile) { - return; + if (Program.GlobalConfig.LogToFile) { + FileTarget fileTarget = new FileTarget("File") { + FileName = Program.LogFile, + Layout = Layout + }; + + config.AddTarget(fileTarget); + config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, fileTarget)); } - lock (FileLock) { - if (!LogToFile) { - return; - } + if (Program.IsRunningAsService) { + EventLogTarget eventLogTarget = new EventLogTarget("EventLog") { + Layout = Layout + }; - try { - File.Delete(Program.LogFile); - } catch (Exception e) { - LogToFile = false; - LogGenericException(e); - } + config.AddTarget(eventLogTarget); + config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, eventLogTarget)); } + + ColoredConsoleTarget consoleTarget = new ColoredConsoleTarget("Console") { + Layout = Layout + }; + + config.AddTarget(consoleTarget); + config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget)); + + LogManager.Configuration = config; } + // Ideally, those two should disable/enable only console logging + // But for some reason removing console rule/target doesn't seem to work + internal static void OnUserInputStart() => LogManager.DisableLogging(); + internal static void OnUserInputEnd() => LogManager.EnableLogging(); + internal static void LogGenericWTF(string message, string botName = "Main", [CallerMemberName] string previousMethodName = null) { if (string.IsNullOrEmpty(message)) { LogNullError(nameof(message), botName); return; } - Log("[!!] WTF: " + previousMethodName + "() <" + botName + "> " + message + ", WTF?"); + Logger.Error($"{botName}|{previousMethodName}() {message}"); } internal static void LogGenericError(string message, string botName = "Main", [CallerMemberName] string previousMethodName = null) { @@ -70,24 +88,16 @@ namespace ArchiSteamFarm { return; } - Log("[!!] ERROR: " + previousMethodName + "() <" + botName + "> " + message); + Logger.Error($"{botName}|{previousMethodName}() {message}"); } internal static void LogGenericException(Exception exception, string botName = "Main", [CallerMemberName] string previousMethodName = null) { - while (true) { - if (exception == null) { - LogNullError(nameof(exception), botName); - return; - } - - Log("[!] EXCEPTION: " + previousMethodName + "() <" + botName + "> " + exception.Message + Environment.NewLine + "StackTrace:" + Environment.NewLine + exception.StackTrace); - if (exception.InnerException != null) { - exception = exception.InnerException; - continue; - } - - break; + if (exception == null) { + LogNullError(nameof(exception), botName); + return; } + + Logger.Error(exception, $"{botName}|{previousMethodName}()"); } internal static void LogGenericWarning(string message, string botName = "Main", [CallerMemberName] string previousMethodName = null) { @@ -96,7 +106,7 @@ namespace ArchiSteamFarm { return; } - Log("[!] WARNING: " + previousMethodName + "() <" + botName + "> " + message); + Logger.Warn($"{botName}|{previousMethodName}() {message}"); } internal static void LogGenericInfo(string message, string botName = "Main", [CallerMemberName] string previousMethodName = null) { @@ -105,20 +115,15 @@ namespace ArchiSteamFarm { return; } - Log("[*] INFO: " + previousMethodName + "() <" + botName + "> " + message); + Logger.Info($"{botName}|{previousMethodName}() {message}"); } - [SuppressMessage("ReSharper", "ExplicitCallerInfoArgument")] internal static void LogNullError(string nullObjectName, string botName = "Main", [CallerMemberName] string previousMethodName = null) { - while (true) { - if (string.IsNullOrEmpty(nullObjectName)) { - nullObjectName = nameof(nullObjectName); - continue; - } - - LogGenericError(nullObjectName + " is null!", botName, previousMethodName); - break; + if (string.IsNullOrEmpty(nullObjectName)) { + return; } + + Logger.Error($"{botName}|{previousMethodName}() {nullObjectName} is null!"); } [Conditional("DEBUG")] @@ -129,42 +134,7 @@ namespace ArchiSteamFarm { return; } - Log("[#] DEBUG: " + previousMethodName + "() <" + botName + "> " + message); - } - - private static void Log(string message) { - if (string.IsNullOrEmpty(message)) { - LogNullError(nameof(message)); - return; - } - - string loggedMessage = DateTime.Now + " " + message + Environment.NewLine; - - // Write on console only when not awaiting response from user - if (!Program.ConsoleIsBusy) { - try { - Console.Write(loggedMessage); - } catch { - // Ignored - } - } - - if (!LogToFile) { - return; - } - - lock (FileLock) { - if (!LogToFile) { - return; - } - - try { - File.AppendAllText(Program.LogFile, loggedMessage); - } catch (Exception e) { - LogToFile = false; - LogGenericException(e); - } - } + Logger.Debug($"{botName}|{previousMethodName}() {message}"); } } } diff --git a/ArchiSteamFarm/Program.cs b/ArchiSteamFarm/Program.cs index b80a5a0ac..faf73ad97 100644 --- a/ArchiSteamFarm/Program.cs +++ b/ArchiSteamFarm/Program.cs @@ -77,9 +77,9 @@ namespace ArchiSteamFarm { private static readonly string ExecutableDirectory = Path.GetDirectoryName(ExecutableFile); private static readonly WCF WCF = new WCF(); + internal static bool IsRunningAsService { get; private set; } internal static GlobalConfig GlobalConfig { get; private set; } internal static GlobalDatabase GlobalDatabase { get; private set; } - internal static bool ConsoleIsBusy { get; private set; } private static Timer AutoUpdatesTimer; private static EMode Mode = EMode.Normal; @@ -286,7 +286,7 @@ namespace ArchiSteamFarm { string result; lock (ConsoleLock) { - ConsoleIsBusy = true; + Logging.OnUserInputStart(); switch (userInputType) { case EUserInputType.DeviceID: Console.Write("<" + botName + "> Please enter your Device ID (including \"android:\"): "); @@ -330,7 +330,7 @@ namespace ArchiSteamFarm { Console.Clear(); // For security purposes } - ConsoleIsBusy = false; + Logging.OnUserInputEnd(); } return !string.IsNullOrEmpty(result) ? result.Trim() : null; @@ -520,6 +520,7 @@ namespace ArchiSteamFarm { foreach (string botName in Directory.EnumerateFiles(ConfigDirectory, "*.json").Select(Path.GetFileNameWithoutExtension)) { switch (botName) { case ASF: + case "Main": case "example": case "minimal": continue; @@ -553,6 +554,7 @@ namespace ArchiSteamFarm { Exit(); } else { // Service + IsRunningAsService = true; using (Service service = new Service()) { ServiceBase.Run(service); } diff --git a/ArchiSteamFarm/packages.config b/ArchiSteamFarm/packages.config index a866853fd..45c0b7174 100644 --- a/ArchiSteamFarm/packages.config +++ b/ArchiSteamFarm/packages.config @@ -4,6 +4,7 @@ + \ No newline at end of file diff --git a/ConfigGenerator/MainForm.cs b/ConfigGenerator/MainForm.cs index 9b7331651..bb5048495 100644 --- a/ConfigGenerator/MainForm.cs +++ b/ConfigGenerator/MainForm.cs @@ -60,6 +60,7 @@ namespace ConfigGenerator { string botName = Path.GetFileNameWithoutExtension(configFile); switch (botName) { case Program.ASF: + case "Main": case "example": case "minimal": continue; @@ -155,6 +156,20 @@ namespace ConfigGenerator { // Get rid of any potential whitespaces in bot name input = Regex.Replace(input, @"\s+", ""); + if (string.IsNullOrEmpty(input)) { + Logging.LogGenericErrorWithoutStacktrace("Your bot name is empty!"); + return; + } + + switch (input) { + case Program.ASF: + case "Main": + case "example": + case "minimal": + Logging.LogGenericErrorWithoutStacktrace("This name is reserved!"); + return; + } + if (ASFConfig.ASFConfigs.Select(config => Path.GetFileNameWithoutExtension(config.FilePath)).Any(fileNameWithoutExtension => (fileNameWithoutExtension == null) || fileNameWithoutExtension.Equals(input))) { Logging.LogGenericErrorWithoutStacktrace("Bot with such name exists already!"); return; diff --git a/packages/NLog.4.4.0-beta13/NLog.4.4.0-beta13.nupkg b/packages/NLog.4.4.0-beta13/NLog.4.4.0-beta13.nupkg new file mode 100644 index 000000000..508520f44 Binary files /dev/null and b/packages/NLog.4.4.0-beta13/NLog.4.4.0-beta13.nupkg differ diff --git a/packages/NLog.4.4.0-beta13/lib/net35/NLog.dll b/packages/NLog.4.4.0-beta13/lib/net35/NLog.dll new file mode 100644 index 000000000..bea438f33 Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/net35/NLog.dll differ diff --git a/packages/NLog.4.4.0-beta13/lib/net40/NLog.dll b/packages/NLog.4.4.0-beta13/lib/net40/NLog.dll new file mode 100644 index 000000000..64310c8df Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/net40/NLog.dll differ diff --git a/packages/NLog.4.4.0-beta13/lib/net45/NLog.dll b/packages/NLog.4.4.0-beta13/lib/net45/NLog.dll new file mode 100644 index 000000000..9e425baf1 Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/net45/NLog.dll differ diff --git a/packages/NLog.4.4.0-beta13/lib/netstandard1.3/NLog.dll b/packages/NLog.4.4.0-beta13/lib/netstandard1.3/NLog.dll new file mode 100644 index 000000000..3d5a0316a Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/netstandard1.3/NLog.dll differ diff --git a/packages/NLog.4.4.0-beta13/lib/netstandard1.5/NLog.dll b/packages/NLog.4.4.0-beta13/lib/netstandard1.5/NLog.dll new file mode 100644 index 000000000..5d5ee3721 Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/netstandard1.5/NLog.dll differ diff --git a/packages/NLog.4.4.0-beta13/lib/sl40/NLog.dll b/packages/NLog.4.4.0-beta13/lib/sl40/NLog.dll new file mode 100644 index 000000000..f65a9fce8 Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/sl40/NLog.dll differ diff --git a/packages/NLog.4.4.0-beta13/lib/sl50/NLog.dll b/packages/NLog.4.4.0-beta13/lib/sl50/NLog.dll new file mode 100644 index 000000000..75a6555ca Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/sl50/NLog.dll differ diff --git a/packages/NLog.4.4.0-beta13/lib/wp80/NLog.dll b/packages/NLog.4.4.0-beta13/lib/wp80/NLog.dll new file mode 100644 index 000000000..64bc29184 Binary files /dev/null and b/packages/NLog.4.4.0-beta13/lib/wp80/NLog.dll differ