diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index c17dbea8..1d2be8c9 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -254,6 +254,7 @@ namespace Shadowsocks.Controller { _config.isVerboseLogging = enabled; SaveConfig(_config); + NLogConfig.LoadConfiguration(); // reload nlog VerboseLoggingStatusChanged?.Invoke(this, new EventArgs()); } @@ -477,6 +478,9 @@ namespace Shadowsocks.Controller Encryption.RNG.Reload(); // some logic in configuration updated the config when saving, we need to read it again _config = Configuration.Load(); + + NLogConfig.LoadConfiguration(); + StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); diff --git a/shadowsocks-csharp/Data/NLog.config b/shadowsocks-csharp/Data/NLog.config index 4b779775..4f9d27e3 100644 --- a/shadowsocks-csharp/Data/NLog.config +++ b/shadowsocks-csharp/Data/NLog.config @@ -1,10 +1,11 @@  - + - - + \ No newline at end of file diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index f2f54b08..db686288 100644 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -36,10 +36,14 @@ namespace Shadowsocks.Model public bool autoCheckUpdate; public bool checkPreRelease; public bool isVerboseLogging; + //public NLogConfig.LogLevel logLevel; public LogViewerConfig logViewer; public ProxyConfig proxy; public HotkeyConfig hotkey; + [JsonIgnore] + NLogConfig nLogConfig; + private static readonly string CONFIG_FILE = "gui-config.json"; [JsonIgnore] public string localHost => GetLocalHost(); @@ -104,6 +108,28 @@ namespace Shadowsocks.Model config.proxy.CheckConfig(); + try + { + config.nLogConfig = NLogConfig.LoadXML(); + switch (config.nLogConfig.GetLogLevel()) + { + case NLogConfig.LogLevel.Fatal: + case NLogConfig.LogLevel.Error: + case NLogConfig.LogLevel.Warn: + case NLogConfig.LogLevel.Info: + config.isVerboseLogging = false; + break; + case NLogConfig.LogLevel.Debug: + case NLogConfig.LogLevel.Trace: + config.isVerboseLogging = true; + break; + } + } + catch (Exception e) + { + logger.Error(e, "Cannot get the log level from NLog config file."); + } + return config; } catch (Exception e) @@ -122,7 +148,7 @@ namespace Shadowsocks.Model }, logViewer = new LogViewerConfig(), proxy = new ProxyConfig(), - hotkey = new HotkeyConfig() + hotkey = new HotkeyConfig(), }; } } @@ -145,6 +171,16 @@ namespace Shadowsocks.Model sw.Write(jsonString); sw.Flush(); } + try + { + // apply changs to NLog.config + config.nLogConfig.SetLogLevel(config.isVerboseLogging? NLogConfig.LogLevel.Trace: NLogConfig.LogLevel.Info); + NLogConfig.SaveXML(config.nLogConfig); + } + catch(Exception e) + { + logger.Error(e, "Cannot set the log level"); + } } catch (IOException e) { diff --git a/shadowsocks-csharp/Model/NlogConfig.cs b/shadowsocks-csharp/Model/NlogConfig.cs new file mode 100644 index 00000000..fe460a5f --- /dev/null +++ b/shadowsocks-csharp/Model/NlogConfig.cs @@ -0,0 +1,117 @@ +using NLog; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace Shadowsocks.Model +{ + public class NLogConfig + { + public enum LogLevel + { + Fatal, + Error, + Warn, + Info, + Debug, + Trace, + } + + const string NLOG_CONFIG_FILE_NAME = "NLog.config"; + const string MIN_LEVEL_ATTRIBUTE = "minlevel"; + const string FILE_NAME_ATTRIBUTE = "fileName"; + + XmlDocument doc = new XmlDocument(); + XmlElement logLevelElement; + XmlElement logFileNameElement; + + /// + /// Load the NLog config xml file content + /// + public static NLogConfig LoadXML() + { + NLogConfig config = new NLogConfig(); + config.doc.Load(NLOG_CONFIG_FILE_NAME); + config.logLevelElement = (XmlElement)SelectSingleNode(config.doc, "//nlog:logger[@name='*']"); + config.logFileNameElement = (XmlElement)SelectSingleNode(config.doc, "//nlog:target[@name='file']"); + return config; + } + + /// + /// Save the content to NLog config xml file + /// + public static void SaveXML(NLogConfig nLogConfig) + { + nLogConfig.doc.Save(NLOG_CONFIG_FILE_NAME); + } + + + /// + /// Get the current minLogLevel from xml file + /// + /// + public LogLevel GetLogLevel() + { + LogLevel level = LogLevel.Warn; + string levelStr = logLevelElement.GetAttribute(MIN_LEVEL_ATTRIBUTE); + Enum.TryParse(levelStr, out level); + return level; + } + + /// + /// Get the target fileName from xml file + /// + /// + public string GetLogFileName() + { + return logFileNameElement.GetAttribute(FILE_NAME_ATTRIBUTE); + } + + /// + /// Set the minLogLevel to xml file + /// + /// + public void SetLogLevel(LogLevel logLevel) + { + logLevelElement.SetAttribute(MIN_LEVEL_ATTRIBUTE, logLevel.ToString("G")); + } + + /// + /// Set the target fileName to xml file + /// + /// + public void SetLogFileName(string fileName) + { + logFileNameElement.SetAttribute(FILE_NAME_ATTRIBUTE, fileName); + } + + private static XmlNode SelectSingleNode(XmlDocument doc, string xpath) + { + XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable); + manager.AddNamespace("nlog", "http://www.nlog-project.org/schemas/NLog.xsd"); + //return doc.SelectSingleNode("//nlog:logger[(@shadowsocks='managed') and (@name='*')]", manager); + return doc.SelectSingleNode(xpath, manager); + } + + /// + /// Extract the pre-defined NLog configuration file is does not exist. Then reload the Nlog configuration. + /// + public static void TouchAndApplyNLogConfig() + { + if (!File.Exists(NLOG_CONFIG_FILE_NAME)) + { + File.WriteAllText(NLOG_CONFIG_FILE_NAME, Properties.Resources.NLog_config); + LogManager.LoadConfiguration(NLOG_CONFIG_FILE_NAME); + } + } + + public static void LoadConfiguration() + { + LogManager.LoadConfiguration(NLOG_CONFIG_FILE_NAME); + } + } +} diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index b85e6ced..906ea685 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -27,7 +27,7 @@ namespace Shadowsocks static void Main(string[] args) { // todo: initialize the NLog configuartion - TouchAndApplyNLogConfig(); + Model.NLogConfig.TouchAndApplyNLogConfig(); // .NET Framework 4.7.2 on Win7 compatibility System.Net.ServicePointManager.SecurityProtocol |= @@ -97,16 +97,6 @@ namespace Shadowsocks } } - private static void TouchAndApplyNLogConfig() - { - string NLogConfigFileName = "NLog.config"; - if (!File.Exists(NLogConfigFileName)) - { - File.WriteAllText(NLogConfigFileName, Properties.Resources.NLog_config); - LogManager.LoadConfiguration(NLogConfigFileName); - } - } - private static int exited = 0; private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index 6209a376..dffd5271 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -61,7 +61,7 @@ namespace Shadowsocks.Util public enum WindowsThemeMode { Dark, Light } // Support on Windows 10 1903+ - public static WindowsThemeMode GetWindows10SystemThemeSetting(bool isVerbose) + public static WindowsThemeMode GetWindows10SystemThemeSetting() { WindowsThemeMode themeMode = WindowsThemeMode.Dark; try @@ -81,11 +81,10 @@ namespace Shadowsocks.Util } catch { - if (isVerbose) - { - logger.Info( - $"Cannot get Windows 10 system theme mode, return default value 0 (dark mode)."); - } + + logger.Info( + $"Cannot get Windows 10 system theme mode, return default value 0 (dark mode)."); + } return themeMode; } diff --git a/shadowsocks-csharp/View/LogForm.cs b/shadowsocks-csharp/View/LogForm.cs index 2f0e3fcc..16f2ad6e 100644 --- a/shadowsocks-csharp/View/LogForm.cs +++ b/shadowsocks-csharp/View/LogForm.cs @@ -41,13 +41,16 @@ namespace Shadowsocks.View TextAnnotation outboundAnnotation = new TextAnnotation(); #endregion - public LogForm(ShadowsocksController controller, string filename=null) + public LogForm(ShadowsocksController controller) { this.controller = controller; - this.filename = filename; + InitializeComponent(); Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); + var nLogConfig = NLogConfig.LoadXML(); + this.filename = nLogConfig.GetLogFileName(); + LogViewerConfig config = controller.GetConfigurationCopy().logViewer; topMostTrigger = config.topMost; @@ -173,7 +176,7 @@ namespace Shadowsocks.View string line = ""; StringBuilder appendText = new StringBuilder(1024); while ((line = reader.ReadLine()) != null) - appendText.Append(line + Environment.NewLine); + appendText.AppendLine(line); LogMessageTextBox.AppendText(appendText.ToString()); LogMessageTextBox.ScrollToCaret(); @@ -197,7 +200,7 @@ namespace Shadowsocks.View while ((line = reader.ReadLine()) != null) { changed = true; - appendText.Append(line + Environment.NewLine); + appendText.AppendLine(line); } if (changed) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 7f310d2b..02be5162 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -222,7 +222,7 @@ namespace Shadowsocks.View { Color colorMask = Color.White; - Utils.WindowsThemeMode currentWindowsThemeMode = Utils.GetWindows10SystemThemeSetting(controller.GetCurrentConfiguration().isVerboseLogging); + Utils.WindowsThemeMode currentWindowsThemeMode = Utils.GetWindows10SystemThemeSetting(); if (isProxyEnabled) { diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 053234a4..bf562337 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -132,6 +132,7 @@ + diff --git a/shadowsocks-windows.sln b/shadowsocks-windows.sln index 1c24be82..d0048437 100644 --- a/shadowsocks-windows.sln +++ b/shadowsocks-windows.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.10 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shadowsocks-csharp\shadowsocks-csharp.csproj", "{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}" EndProject @@ -12,21 +12,30 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShadowsocksTest", "test\Sha EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|Any CPU.ActiveCfg = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.ActiveCfg = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Build.0 = Debug|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Deploy.0 = Debug|x86 + {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|Any CPU.ActiveCfg = Release|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.ActiveCfg = Release|x86 {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.Build.0 = Release|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Debug|Any CPU.ActiveCfg = Debug|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.ActiveCfg = Debug|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.Build.0 = Debug|x86 + {45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.ActiveCfg = Release|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.ActiveCfg = Release|x86 {45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F7E7D35B-4FDA-4385-95CF-09DADED042EA} + EndGlobalSection EndGlobal