diff --git a/shadowsocks-csharp/Controller/Logging.cs b/shadowsocks-csharp/Controller/Logging.cs index 81f16dd8..c9f753d0 100755 --- a/shadowsocks-csharp/Controller/Logging.cs +++ b/shadowsocks-csharp/Controller/Logging.cs @@ -1,27 +1,28 @@ using System; -using System.Collections.Generic; using System.IO; using System.Net.Sockets; -using System.Text; namespace Shadowsocks.Controller { public class Logging { public static string LogFile; - - public static bool OpenLogFile() + private static FileStream _logFileStream; + private static StreamWriter _streamWriter; + public static bool AttatchToConsole() { try { string temppath = Path.GetTempPath(); LogFile = Path.Combine(temppath, "shadowsocks.log"); - FileStream fs = new FileStream(LogFile, FileMode.Append); - StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs); - sw.AutoFlush = true; - Console.SetOut(sw); - Console.SetError(sw); - + if (_logFileStream == null) + { + _logFileStream = new FileStream(LogFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); + _logFileStream.Seek(_logFileStream.Length, SeekOrigin.Begin); + _streamWriter = new StreamWriterWithTimestamp(_logFileStream) { AutoFlush = true }; + Console.SetOut(_streamWriter); + Console.SetError(_streamWriter); + } return true; } catch (IOException e) @@ -61,12 +62,33 @@ namespace Shadowsocks.Controller } } + /// + /// Clear the log file + /// + /// + public static bool Clear() + { + if (_logFileStream != null) + { + try + { + _logFileStream.SetLength(0); + return true; + } + catch (IOException ioException) + { + Console.WriteLine(ioException); + } + } + return false; + } } // Simply extended System.IO.StreamWriter for adding timestamp workaround public class StreamWriterWithTimestamp : StreamWriter { - public StreamWriterWithTimestamp(Stream stream) : base(stream) + public StreamWriterWithTimestamp(Stream stream) + : base(stream) { } diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index e092575c..1d5d6213 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -20,6 +20,7 @@ Edit User Rule for GFWList...=编辑 GFWList 的用户规则... Show QRCode...=显示二维码... Scan QRCode from Screen...=扫描屏幕上的二维码... Show Logs...=显示日志... +Clear Logs...=清除日志... About...=关于... Quit=退出 Edit Servers=编辑服务器 diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 8ca485d7..c5601893 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -1,12 +1,12 @@ -using Shadowsocks.Controller; -using Shadowsocks.Properties; -using Shadowsocks.View; -using System; -using System.Collections.Generic; +using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Windows.Forms; +using Shadowsocks.Controller; +using Shadowsocks.Properties; +using Shadowsocks.Util; +using Shadowsocks.View; namespace Shadowsocks { @@ -18,8 +18,8 @@ namespace Shadowsocks [STAThread] static void Main() { - Util.Utils.ReleaseMemory(); - using (Mutex mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F")) + Utils.ReleaseMemory(); + using (var mutex = new Mutex(false, "Global\\" + "71981632-A427-497F-AB91-241CD227EC1F")) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); @@ -29,18 +29,17 @@ namespace Shadowsocks Process[] oldProcesses = Process.GetProcessesByName("Shadowsocks"); if (oldProcesses.Length > 0) { - Process oldProcess = oldProcesses[0]; } - MessageBox.Show("Shadowsocks is already running.\n\nFind Shadowsocks icon in your notify tray."); + MessageBox.Show(Resources.MultiProcess); return; } Directory.SetCurrentDirectory(Application.StartupPath); #if !DEBUG - Logging.OpenLogFile(); + Logging.AttatchToConsole(); #endif ShadowsocksController controller = new ShadowsocksController(); - MenuViewController viewController = new MenuViewController(controller); + MenuViewController.AttachMenu(controller); controller.Start(); diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index a5d9c107..0d6c77c4 100755 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.34209 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.0 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace Shadowsocks.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// 一个强类型的资源类,用于查找本地化的字符串等。 /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace Shadowsocks.Properties { } /// - /// Returns the cached ResourceManager instance used by this class. + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace Shadowsocks.Properties { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] abp_js { get { @@ -71,33 +71,30 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to Shadowsocks=Shadowsocks - ///Enable System Proxy=启用系统代理 - ///Mode=系统代理模式 - ///PAC=PAC 模式 - ///Global=全局模式 - ///Servers=服务器 - ///Edit Servers...=编辑服务器... - ///Start on Boot=开机启动 - ///Allow Clients from LAN=允许来自局域网的连接 - ///Edit PAC File...=编辑 PAC 文件... - ///Edit User Rule for GFWList...=编辑 GFWList 的用户规则... - ///Show QRCode...=显示二维码... - ///Scan QRCode from Screen...=扫描屏幕上的二维码... - ///Show Logs...=显示日志... - ///About...=关于... - ///Quit=退出 - ///Edit Servers=编辑服务器 - ///&Add=添加(&A) - ///&Delete=删除(&D) - ///Server=服务器 - ///Server IP=服务器 IP - ///Server Port=服务器端口 - ///Password=密码 - ///Encryption=加密 - ///Proxy Port=代理端口 - ///Remarks=备注 - ///OK= [rest of string was truncated]";. + /// 查找类似 # translation for Simplified Chinese + /// + ///Shadowsocks=Shadowsocks + /// + ///# Menu items + /// + ///Enable System Proxy=启用系统代理 + ///Mode=系统代理模式 + ///PAC=PAC 模式 + ///Global=全局模式 + ///Servers=服务器 + ///Edit Servers...=编辑服务器... + ///Start on Boot=开机启动 + ///Allow Clients from LAN=允许来自局域网的连接 + ///Local PAC=使用本地 PAC + ///Online PAC=使用在线 PAC + ///Edit Local PAC File...=编辑本地 PAC 文件... + ///Update Local PAC from GFWList=从 GFWList 更新本地 PAC + ///Edit User Rule for GFWList...=编辑 GFWList 的用户规则... + ///Show QRCode...=显示二维码... + ///Scan QRCode from Screen...=扫描屏幕上的二维码... + ///Show Logs...=显示日志... + ///Clear Logs...=清除日志... + /// [字符串的其余部分被截断]"; 的本地化字符串。 /// internal static string cn { get { @@ -106,7 +103,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] libsscrypto_dll { get { @@ -116,16 +113,27 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to proxyAddress = "__POLIPO_BIND_IP__" - ///proxyPort = 8123 - /// - ///socksParentProxy = "127.0.0.1:__SOCKS_PORT__" - ///socksProxyType = socks5 - ///diskCacheRoot = "" - ///localDocumentRoot = "" - /// + /// 查找类似 Shadowsocks is already running. + /// + ///Find Shadowsocks icon in your notify tray. 的本地化字符串。 + /// + internal static string MultiProcess { + get { + return ResourceManager.GetString("MultiProcess", resourceCulture); + } + } + + /// + /// 查找类似 proxyAddress = "__POLIPO_BIND_IP__" + ///proxyPort = 8123 + /// + ///socksParentProxy = "127.0.0.1:__SOCKS_PORT__" + ///socksProxyType = socks5 + ///diskCacheRoot = "" + ///localDocumentRoot = "" + /// ///allowedPorts = 1-65535 - ///tunnelAllowedPorts = 1-65535. + ///tunnelAllowedPorts = 1-65535 的本地化字符串。 /// internal static string polipo_config { get { @@ -134,7 +142,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] polipo_exe { get { @@ -144,7 +152,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] proxy_pac_txt { get { @@ -154,7 +162,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss16 { get { @@ -164,7 +172,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss20 { get { @@ -174,7 +182,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss24 { get { @@ -184,7 +192,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ssw128 { get { @@ -194,9 +202,9 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to ! Put user rules line by line in this file. + /// 查找类似 ! Put user rules line by line in this file. ///! See https://adblockplus.org/en/filter-cheatsheet - ///. + /// 的本地化字符串。 /// internal static string user_rule { get { diff --git a/shadowsocks-csharp/Properties/Resources.resx b/shadowsocks-csharp/Properties/Resources.resx index aa851e6b..41ba3382 100755 --- a/shadowsocks-csharp/Properties/Resources.resx +++ b/shadowsocks-csharp/Properties/Resources.resx @@ -151,4 +151,9 @@ ..\data\user-rule.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + Shadowsocks is already running. + +Find Shadowsocks icon in your notify tray. + \ No newline at end of file diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index ff5a018c..abbd5ebb 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -1,12 +1,13 @@ -using Shadowsocks.Controller; -using Shadowsocks.Model; -using Shadowsocks.Properties; -using System; -using System.Collections.Generic; +using System; using System.Diagnostics; using System.Drawing; -using System.Text; +using System.IO; using System.Windows.Forms; +using Microsoft.VisualBasic; +using Shadowsocks.Controller; +using Shadowsocks.Model; +using Shadowsocks.Properties; +using Shadowsocks.Util; using ZXing; using ZXing.Common; using ZXing.QrCode; @@ -18,7 +19,7 @@ namespace Shadowsocks.View // yes this is just a menu view controller // when config form is closed, it moves away from RAM // and it should just do anything related to the config form - + private ShadowsocksController controller; private UpdateChecker updateChecker; @@ -44,7 +45,12 @@ namespace Shadowsocks.View private ConfigForm configForm; private string _urlToOpen; - public MenuViewController(ShadowsocksController controller) + public static MenuViewController AttachMenu(ShadowsocksController controller) + { + return new MenuViewController(controller); + } + + private MenuViewController(ShadowsocksController controller) { this.controller = controller; @@ -80,7 +86,7 @@ namespace Shadowsocks.View } } - void controller_Errored(object sender, System.IO.ErrorEventArgs e) + void controller_Errored(object sender, ErrorEventArgs e) { MessageBox.Show(e.GetException().ToString(), String.Format(I18N.GetString("Shadowsocks Error: {0}"), e.GetException().Message)); } @@ -171,6 +177,7 @@ namespace Shadowsocks.View this.ShareOverLANItem = CreateMenuItem("Allow Clients from LAN", new EventHandler(this.ShareOverLANItem_Click)), new MenuItem("-"), CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)), + CreateMenuItem("Clear Logs...",ClearLogItem_Click), CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)), new MenuItem("-"), CreateMenuItem("Quit", new EventHandler(this.Quit_Click)) @@ -204,7 +211,7 @@ namespace Shadowsocks.View { string argument = @"/select, " + e.Path; - System.Diagnostics.Process.Start("explorer.exe", argument); + Process.Start("explorer.exe", argument); } void ShowBalloonTip(string title, string content, ToolTipIcon icon, int timeout) @@ -215,7 +222,7 @@ namespace Shadowsocks.View _notifyIcon.ShowBalloonTip(timeout); } - void controller_UpdatePACFromGFWListError(object sender, System.IO.ErrorEventArgs e) + void controller_UpdatePACFromGFWListError(object sender, ErrorEventArgs e) { ShowBalloonTip(I18N.GetString("Failed to update PAC file"), e.GetException().Message, ToolTipIcon.Error, 5000); Logging.LogUsefulException(e.GetException()); @@ -236,7 +243,7 @@ namespace Shadowsocks.View void notifyIcon1_BalloonTipClicked(object sender, EventArgs e) { - System.Diagnostics.Process.Start(updateChecker.LatestVersionURL); + Process.Start(updateChecker.LatestVersionURL); _notifyIcon.BalloonTipClicked -= notifyIcon1_BalloonTipClicked; } @@ -297,7 +304,7 @@ namespace Shadowsocks.View void configForm_FormClosed(object sender, FormClosedEventArgs e) { configForm = null; - Util.Utils.ReleaseMemory(); + Utils.ReleaseMemory(); ShowFirstTimeBalloon(); } @@ -318,7 +325,7 @@ namespace Shadowsocks.View if (_isFirstRun) { _notifyIcon.BalloonTipTitle = I18N.GetString("Shadowsocks is here"); - _notifyIcon.BalloonTipText = I18N.GetString("You can turn on/off Shadowsocks in the context menu"); + _notifyIcon.BalloonTipText = I18N.GetString("You can turn on/off Shadowsocks in the context menu"); _notifyIcon.BalloonTipIcon = ToolTipIcon.Info; _notifyIcon.ShowBalloonTip(0); _isFirstRun = false; @@ -384,7 +391,12 @@ namespace Shadowsocks.View { string argument = Logging.LogFile; - System.Diagnostics.Process.Start("notepad.exe", argument); + Process.Start("notepad.exe", argument); + } + + private void ClearLogItem_Click(object sender, EventArgs e) + { + Logging.Clear(); } private void QRCodeItem_Click(object sender, EventArgs e) @@ -489,12 +501,14 @@ namespace Shadowsocks.View Process.Start(_urlToOpen); } - private void AutoStartupItem_Click(object sender, EventArgs e) { - AutoStartupItem.Checked = !AutoStartupItem.Checked; - if (!AutoStartup.Set(AutoStartupItem.Checked)) { - MessageBox.Show(I18N.GetString("Failed to update registry")); - } - } + private void AutoStartupItem_Click(object sender, EventArgs e) + { + AutoStartupItem.Checked = !AutoStartupItem.Checked; + if (!AutoStartup.Set(AutoStartupItem.Checked)) + { + MessageBox.Show(I18N.GetString("Failed to update registry")); + } + } private void LocalPACItem_Click(object sender, EventArgs e) { @@ -528,7 +542,7 @@ namespace Shadowsocks.View private void UpdateOnlinePACURLItem_Click(object sender, EventArgs e) { string origPacUrl = controller.GetConfiguration().pacUrl; - string pacUrl = Microsoft.VisualBasic.Interaction.InputBox( + string pacUrl = Interaction.InputBox( I18N.GetString("Please input PAC Url"), I18N.GetString("Edit Online PAC URL"), origPacUrl, -1, -1);