From 5e0ccffa9680b28d1e4bd574e852ea9c76bcce87 Mon Sep 17 00:00:00 2001 From: Student Main Date: Thu, 17 Jan 2019 16:55:46 +0800 Subject: [PATCH 1/3] Register restart after system reboot, #2154 --- .../Controller/System/AutoStartup.cs | 55 ++++++++++++++++--- shadowsocks-csharp/Program.cs | 1 + 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/shadowsocks-csharp/Controller/System/AutoStartup.cs b/shadowsocks-csharp/Controller/System/AutoStartup.cs index 7c7b0dc4..923c16f5 100644 --- a/shadowsocks-csharp/Controller/System/AutoStartup.cs +++ b/shadowsocks-csharp/Controller/System/AutoStartup.cs @@ -1,5 +1,6 @@ using System; using System.Reflection; +using System.Runtime.InteropServices; using System.Windows.Forms; using Microsoft.Win32; using Shadowsocks.Util; @@ -20,8 +21,9 @@ namespace Shadowsocks.Controller try { runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true); - if ( runKey == null ) { - Logging.Error( @"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run" ); + if (runKey == null) + { + Logging.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run"); return false; } if (enabled) @@ -32,6 +34,8 @@ namespace Shadowsocks.Controller { runKey.DeleteValue(Key); } + // When autostartup setting change, change RegisterForRestart state to avoid start 2 times + RegisterForRestart(!enabled); return true; } catch (Exception e) @@ -43,10 +47,12 @@ namespace Shadowsocks.Controller { if (runKey != null) { - try { + try + { runKey.Close(); runKey.Dispose(); - } catch (Exception e) + } + catch (Exception e) { Logging.LogUsefulException(e); } } } @@ -58,7 +64,8 @@ namespace Shadowsocks.Controller try { runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true); - if (runKey == null) { + if (runKey == null) + { Logging.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run"); return false; } @@ -89,13 +96,47 @@ namespace Shadowsocks.Controller { if (runKey != null) { - try { + try + { runKey.Close(); runKey.Dispose(); - } catch (Exception e) + } + catch (Exception e) { Logging.LogUsefulException(e); } } } } + + [DllImport("kernel32.dll", SetLastError = true)] + static extern int RegisterApplicationRestart([MarshalAs(UnmanagedType.LPWStr)] string commandLineArgs, int Flags); + + [DllImport("kernel32.dll", SetLastError = true)] + static extern int UnregisterApplicationRestart(); + + enum ApplicationRestartFlags + { + RESTART_NO_CRASH = 1, + RESTART_NO_HANG = 2, + RESTART_NO_PATCH = 4, + RESTART_NO_REBOOT = 8, + } + + // regist restart after system reboot/update + public static void RegisterForRestart(bool regist) + { + // requested regist and not autostart + if (regist && !Check()) + { + // param 1 is process command param + RegisterApplicationRestart(null, (int)ApplicationRestartFlags.RESTART_NO_CRASH | (int)ApplicationRestartFlags.RESTART_NO_HANG); + Logging.Debug("Register restart after system reboot"); + } + // request unregist, unregist has no side effect + else if (!regist) + { + UnregisterApplicationRestart(); + Logging.Debug("Unregister restart after system reboot"); + } + } } } diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 87da70c6..8914ccef 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -54,6 +54,7 @@ namespace Shadowsocks SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + AutoStartup.RegisterForRestart(true); if (!mutex.WaitOne(0, false)) { From 207a977e4a66014e145a9049305cea88f7f1bd49 Mon Sep 17 00:00:00 2001 From: Student Main Date: Thu, 17 Jan 2019 23:10:57 +0800 Subject: [PATCH 2/3] Fix typo --- .../Controller/System/AutoStartup.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/shadowsocks-csharp/Controller/System/AutoStartup.cs b/shadowsocks-csharp/Controller/System/AutoStartup.cs index 923c16f5..8aa1f6d5 100644 --- a/shadowsocks-csharp/Controller/System/AutoStartup.cs +++ b/shadowsocks-csharp/Controller/System/AutoStartup.cs @@ -121,18 +121,20 @@ namespace Shadowsocks.Controller RESTART_NO_REBOOT = 8, } - // regist restart after system reboot/update - public static void RegisterForRestart(bool regist) + // register restart after system reboot/update + public static void RegisterForRestart(bool register) { - // requested regist and not autostart - if (regist && !Check()) + // requested register and not autostartup + if (register && !Check()) { - // param 1 is process command param + // first parameter is process command line parameter + // if ss-windows use it in future, remember pass it + // needn't include the name of the executable in the command line RegisterApplicationRestart(null, (int)ApplicationRestartFlags.RESTART_NO_CRASH | (int)ApplicationRestartFlags.RESTART_NO_HANG); Logging.Debug("Register restart after system reboot"); } - // request unregist, unregist has no side effect - else if (!regist) + // requested unregister, which has no side effect + else if (!register) { UnregisterApplicationRestart(); Logging.Debug("Unregister restart after system reboot"); From 447632ff07e8770747d7f211b14f10a0fef7c5a2 Mon Sep 17 00:00:00 2001 From: Student Main Date: Fri, 18 Jan 2019 00:06:56 +0800 Subject: [PATCH 3/3] set command line parameter when register restart, for future --- shadowsocks-csharp/Controller/System/AutoStartup.cs | 13 ++++++++++--- shadowsocks-csharp/Program.cs | 7 +++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/shadowsocks-csharp/Controller/System/AutoStartup.cs b/shadowsocks-csharp/Controller/System/AutoStartup.cs index 8aa1f6d5..9f3e5ff2 100644 --- a/shadowsocks-csharp/Controller/System/AutoStartup.cs +++ b/shadowsocks-csharp/Controller/System/AutoStartup.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; @@ -127,11 +129,16 @@ namespace Shadowsocks.Controller // requested register and not autostartup if (register && !Check()) { + // escape command line parameter + string[] args = new List(Program.Args) + .Select(p => p.Replace("\"", "\\\"")) // escape " to \" + .Select(p => p.IndexOf(" ") >= 0 ? "\"" + p + "\"" : p) // encapsule with " + .ToArray(); + string cmdline = string.Join(" ", args); // first parameter is process command line parameter - // if ss-windows use it in future, remember pass it // needn't include the name of the executable in the command line - RegisterApplicationRestart(null, (int)ApplicationRestartFlags.RESTART_NO_CRASH | (int)ApplicationRestartFlags.RESTART_NO_HANG); - Logging.Debug("Register restart after system reboot"); + RegisterApplicationRestart(cmdline, (int)ApplicationRestartFlags.RESTART_NO_CRASH | (int)ApplicationRestartFlags.RESTART_NO_HANG); + Logging.Debug("Register restart after system reboot, command line:" + cmdline); } // requested unregister, which has no side effect else if (!register) diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 8914ccef..a1763e38 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -16,13 +16,16 @@ namespace Shadowsocks { public static ShadowsocksController MainController { get; private set; } public static MenuViewController MenuController { get; private set; } - + public static string[] Args { get; private set; } /// /// 应用程序的主入口点。 /// + /// [STAThread] - static void Main() + static void Main(string[] args) { + // store args for further use + Args = args; // Check OS since we are using dual-mode socket if (!Utils.IsWinVistaOrHigher()) {