You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Program.cs 8.1 kB

11 years ago
11 years ago
11 years ago
13 years ago
13 years ago
11 years ago
13 years ago
9 years ago
6 years ago
13 years ago
13 years ago
13 years ago
6 years ago
6 years ago
11 years ago
11 years ago
11 years ago
9 years ago
9 years ago
11 years ago
13 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Threading;
  5. using System.Windows.Forms;
  6. using NLog;
  7. using Microsoft.Win32;
  8. using Shadowsocks.Controller;
  9. using Shadowsocks.Controller.Hotkeys;
  10. using Shadowsocks.Util;
  11. using Shadowsocks.View;
  12. namespace Shadowsocks
  13. {
  14. static class Program
  15. {
  16. private static Logger logger = LogManager.GetCurrentClassLogger();
  17. public static ShadowsocksController MainController { get; private set; }
  18. public static MenuViewController MenuController { get; private set; }
  19. public static string[] Args { get; private set; }
  20. [System.Runtime.InteropServices.DllImport("user32.dll")]
  21. private static extern bool SetProcessDPIAware();
  22. /// <summary>
  23. /// 应用程序的主入口点。
  24. /// </summary>
  25. /// </summary>
  26. [STAThread]
  27. static void Main(string[] args)
  28. {
  29. // todo: initialize the NLog configuartion
  30. Model.NLogConfig.TouchAndApplyNLogConfig();
  31. // .NET Framework 4.7.2 on Win7 compatibility
  32. System.Net.ServicePointManager.SecurityProtocol |=
  33. System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12;
  34. // store args for further use
  35. Args = args;
  36. // Check OS since we are using dual-mode socket
  37. if (!Utils.IsWinVistaOrHigher())
  38. {
  39. MessageBox.Show(I18N.GetString("Unsupported operating system, use Windows Vista at least."),
  40. "Shadowsocks Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
  41. return;
  42. }
  43. #if NET472
  44. // Check .NET Framework version
  45. if (!Utils.IsSupportedRuntimeVersion())
  46. {
  47. if (DialogResult.OK == MessageBox.Show(I18N.GetString("Unsupported .NET Framework, please update to {0} or later.", "4.7.2"),
  48. "Shadowsocks Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error))
  49. {
  50. //Process.Start("https://www.microsoft.com/download/details.aspx?id=53344"); // 4.6.2
  51. Process.Start("https://dotnet.microsoft.com/download/dotnet-framework/net472");
  52. }
  53. return;
  54. }
  55. if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
  56. #else
  57. Application.SetHighDpiMode(HighDpiMode.SystemAware);
  58. #endif
  59. Utils.ReleaseMemory(true);
  60. using (Mutex mutex = new Mutex(false, $"Global\\Shadowsocks_{Application.StartupPath.GetHashCode()}"))
  61. {
  62. Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
  63. // handle UI exceptions
  64. Application.ThreadException += Application_ThreadException;
  65. // handle non-UI exceptions
  66. AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
  67. Application.ApplicationExit += Application_ApplicationExit;
  68. SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
  69. Application.EnableVisualStyles();
  70. Application.SetCompatibleTextRenderingDefault(false);
  71. AutoStartup.RegisterForRestart(true);
  72. if (!mutex.WaitOne(0, false))
  73. {
  74. Process[] oldProcesses = Process.GetProcessesByName("Shadowsocks");
  75. if (oldProcesses.Length > 0)
  76. {
  77. Process oldProcess = oldProcesses[0];
  78. }
  79. MessageBox.Show(I18N.GetString("Find Shadowsocks icon in your notify tray.")
  80. + Environment.NewLine
  81. + I18N.GetString("If you want to start multiple Shadowsocks, make a copy in another directory."),
  82. I18N.GetString("Shadowsocks is already running."));
  83. return;
  84. }
  85. Directory.SetCurrentDirectory(Application.StartupPath);
  86. #if DEBUG
  87. // truncate privoxy log file while debugging
  88. string privoxyLogFilename = Utils.GetTempPath("privoxy.log");
  89. if (File.Exists(privoxyLogFilename))
  90. using (new FileStream(privoxyLogFilename, FileMode.Truncate)) { }
  91. #endif
  92. MainController = new ShadowsocksController();
  93. MenuController = new MenuViewController(MainController);
  94. HotKeys.Init(MainController);
  95. MainController.Start();
  96. Application.Run();
  97. }
  98. }
  99. private static int exited = 0;
  100. private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
  101. {
  102. if (Interlocked.Increment(ref exited) == 1)
  103. {
  104. string errMsg = e.ExceptionObject.ToString();
  105. logger.Error(errMsg);
  106. MessageBox.Show(
  107. $"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errMsg}",
  108. "Shadowsocks non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
  109. Application.Exit();
  110. }
  111. }
  112. private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
  113. {
  114. if (Interlocked.Increment(ref exited) == 1)
  115. {
  116. string errorMsg = $"Exception Detail: {Environment.NewLine}{e.Exception}";
  117. logger.Error(errorMsg);
  118. MessageBox.Show(
  119. $"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errorMsg}",
  120. "Shadowsocks UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
  121. Application.Exit();
  122. }
  123. }
  124. private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
  125. {
  126. switch (e.Mode)
  127. {
  128. case PowerModes.Resume:
  129. logger.Info("os wake up");
  130. if (MainController != null)
  131. {
  132. System.Threading.Tasks.Task.Factory.StartNew(() =>
  133. {
  134. Thread.Sleep(10 * 1000);
  135. try
  136. {
  137. MainController.Start(false);
  138. logger.Info("controller started");
  139. }
  140. catch (Exception ex)
  141. {
  142. logger.LogUsefulException(ex);
  143. }
  144. });
  145. }
  146. break;
  147. case PowerModes.Suspend:
  148. if (MainController != null)
  149. {
  150. MainController.Stop();
  151. logger.Info("controller stopped");
  152. }
  153. logger.Info("os suspend");
  154. break;
  155. }
  156. }
  157. private static void Application_ApplicationExit(object sender, EventArgs e)
  158. {
  159. // detach static event handlers
  160. Application.ApplicationExit -= Application_ApplicationExit;
  161. SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
  162. Application.ThreadException -= Application_ThreadException;
  163. HotKeys.Destroy();
  164. if (MainController != null)
  165. {
  166. MainController.Stop();
  167. MainController = null;
  168. }
  169. }
  170. }
  171. }