diff --git a/shadowsocks-csharp/Controller/HotkeyReg.cs b/shadowsocks-csharp/Controller/HotkeyReg.cs
index 2ebef212..25b1dd93 100644
--- a/shadowsocks-csharp/Controller/HotkeyReg.cs
+++ b/shadowsocks-csharp/Controller/HotkeyReg.cs
@@ -12,7 +12,7 @@ namespace Shadowsocks.Controller
private static Logger logger = LogManager.GetCurrentClassLogger();
public static void RegAllHotkeys()
{
- var hotkeyConfig = Configuration.Load().hotkey;
+ var hotkeyConfig = Program.MainController.GetCurrentConfiguration().hotkey;
if (hotkeyConfig == null || !hotkeyConfig.RegHotkeysAtStartup)
return;
diff --git a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
index 35c8bbe7..95a3fbcb 100644
--- a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
+++ b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
@@ -192,6 +192,13 @@ namespace Shadowsocks.Controller
return true;
}
+ ///
+ /// Checks if the specified group exists in GeoSite database.
+ ///
+ /// The group name to check for.
+ /// True if the group exists. False if the group doesn't exist.
+ public static bool CheckGeositeGroup(string group) => Geosites.ContainsKey(group);
+
private static string MergePACFile(IList domains, bool blacklist)
{
string abpContent;
diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs
index 7fd9250e..5a84fe8e 100644
--- a/shadowsocks-csharp/Controller/Service/PACServer.cs
+++ b/shadowsocks-csharp/Controller/Service/PACServer.cs
@@ -45,7 +45,7 @@ namespace Shadowsocks.Controller
_config = config;
string usedSecret = _config.secureLocalPac ? $"&secret={PacSecret}" : "";
string contentHash = GetHash(_pacDaemon.GetPACContent());
- PacUrl = $"http://{config.localHost}:{config.localPort}/{RESOURCE_NAME}?hash={contentHash}{usedSecret}";
+ PacUrl = $"http://{config.LocalHost}:{config.localPort}/{RESOURCE_NAME}?hash={contentHash}{usedSecret}";
logger.Debug("Set PAC URL:" + PacUrl);
}
@@ -176,7 +176,6 @@ Connection: Close
";
byte[] response = Encoding.UTF8.GetBytes(responseHead + pacContent);
socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket);
- Utils.ReleaseMemory(true);
}
catch (Exception e)
{
diff --git a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs
index 137d86df..c31e49e1 100644
--- a/shadowsocks-csharp/Controller/Service/UpdateChecker.cs
+++ b/shadowsocks-csharp/Controller/Service/UpdateChecker.cs
@@ -172,7 +172,7 @@ namespace Shadowsocks.Controller
{
WebClient http = new WebClient();
http.Headers.Add("User-Agent", UserAgent);
- http.Proxy = new WebProxy(config.localHost, config.localPort);
+ http.Proxy = new WebProxy(config.LocalHost, config.localPort);
return http;
}
diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs
index cb915ff7..b181f79d 100644
--- a/shadowsocks-csharp/Controller/ShadowsocksController.cs
+++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs
@@ -27,7 +27,6 @@ namespace Shadowsocks.Controller
// manipulates UI
// interacts with low level logic
#region Members definition
- private Thread _ramThread;
private Thread _trafficThread;
private Listener _listener;
@@ -93,10 +92,10 @@ namespace Shadowsocks.Controller
public ShadowsocksController()
{
_config = Configuration.Load();
+ Configuration.Process(ref _config);
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
_strategyManager = new StrategyManager(this);
_pluginsByServer = new ConcurrentDictionary();
- StartReleasingMemory();
StartTrafficStatistics(61);
ProgramUpdated += (o, e) =>
@@ -107,23 +106,34 @@ namespace Shadowsocks.Controller
#region Basic
- public void Start(bool regHotkeys = true)
+ public void Start(bool systemWakeUp = false)
{
- if (_config.updated && regHotkeys)
+ if (_config.firstRunOnNewVersion && !systemWakeUp)
{
- _config.updated = false;
ProgramUpdated.Invoke(this, new UpdatedEventArgs()
{
OldVersion = _config.version,
NewVersion = UpdateChecker.Version,
});
+ // delete pac.txt when regeneratePacOnUpdate is true
+ if (_config.regeneratePacOnUpdate)
+ try
+ {
+ File.Delete(PACDaemon.PAC_FILE);
+ logger.Info("Deleted pac.txt from previous version.");
+ }
+ catch (Exception e)
+ {
+ logger.LogUsefulException(e);
+ }
+ // finish up first run of new version
+ _config.firstRunOnNewVersion = false;
+ _config.version = UpdateChecker.Version;
Configuration.Save(_config);
}
Reload();
- if (regHotkeys)
- {
+ if (!systemWakeUp)
HotkeyReg.RegAllHotkeys();
- }
}
public void Stop()
@@ -154,6 +164,7 @@ namespace Shadowsocks.Controller
Encryption.RNG.Reload();
// some logic in configuration updated the config when saving, we need to read it again
_config = Configuration.Load();
+ Configuration.Process(ref _config);
NLogConfig.LoadConfiguration();
@@ -226,7 +237,6 @@ namespace Shadowsocks.Controller
ConfigChanged?.Invoke(this, new EventArgs());
UpdateSystemProxy();
- Utils.ReleaseMemory(true);
}
protected void SaveConfig(Configuration newConfig)
@@ -394,6 +404,13 @@ namespace Shadowsocks.Controller
ConfigChanged?.Invoke(this, new EventArgs());
}
+ public void ToggleRegeneratePacOnUpdate(bool enabled)
+ {
+ _config.regeneratePacOnUpdate = enabled;
+ SaveConfig(_config);
+ ConfigChanged?.Invoke(this, new EventArgs());
+ }
+
#endregion
#region SIP002
@@ -622,28 +639,6 @@ namespace Shadowsocks.Controller
#endregion
- #region Memory Management
-
- private void StartReleasingMemory()
- {
- _ramThread = new Thread(new ThreadStart(ReleaseMemory))
- {
- IsBackground = true
- };
- _ramThread.Start();
- }
-
- private void ReleaseMemory()
- {
- while (true)
- {
- Utils.ReleaseMemory(false);
- Thread.Sleep(30 * 1000);
- }
- }
-
- #endregion
-
#region Traffic Statistics
private void StartTrafficStatistics(int queueMaxSize)
diff --git a/shadowsocks-csharp/Data/i18n.csv b/shadowsocks-csharp/Data/i18n.csv
index bc9c1f95..f2836232 100644
--- a/shadowsocks-csharp/Data/i18n.csv
+++ b/shadowsocks-csharp/Data/i18n.csv
@@ -28,6 +28,7 @@ Edit Local PAC File...,Редактировать локальный PAC…,编
Update Local PAC from Geosite,Обновить локальный PAC из Geosite,从 Geosite 更新本地 PAC,從 Geosite 更新本機 PAC,Geosite からローカル PAC を更新,Geosite에서 로컬 프록시 자동 구성 파일 업데이트,Mettre à jour le PAC local à partir de Geosite
Edit User Rule for Geosite...,Редактировать свои правила для Geosite,编辑 Geosite 的用户规则...,編輯 Geosite 的使用者規則...,ユーザールールの編集...,Geosite 사용자 수정,Modifier la règle utilisateur pour Geosite ...
Secure Local PAC,Безопасный URL локального PAC,保护本地 PAC,安全本機 PAC,ローカル PAC を保護,로컬 프록시 자동 구성 파일 암호화,Sécuriser PAC local
+Regenerate local PAC on version update,,版本更新后重新生成本地 PAC,版本更新後重新生成本地 PAC,,,
Copy Local PAC URL,Копировать URL локального PAC,复制本地 PAC 网址,複製本機 PAC 網址,ローカル PAC URL をコピー,로컬 프록시 자동 구성 파일 URL 복사,Copier l'URL du PAC local
Share Server Config...,Поделиться конфигурацией сервера…,分享服务器配置...,分享伺服器設定檔...,サーバーの設定を共有...,서버 설정 공유,Partager la configuration du serveur ...
Scan QRCode from Screen...,Сканировать QRCode с экрана…,扫描屏幕上的二维码...,掃描螢幕上的 QR 碼...,画面から QR コードをスキャン...,화면에서 QR코드 스캔,Scanner le QRCode à partir de l'écran ...
diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs
index cd16032b..6ceabb2a 100644
--- a/shadowsocks-csharp/Model/Configuration.cs
+++ b/shadowsocks-csharp/Model/Configuration.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
+using System.Windows;
using Newtonsoft.Json;
using NLog;
using Shadowsocks.Controller;
@@ -27,14 +28,15 @@ namespace Shadowsocks.Model
public bool global;
public bool enabled;
public bool shareOverLan;
- public bool isDefault;
+ public bool firstRun;
public int localPort;
public bool portableMode;
public bool showPluginOutput;
public string pacUrl;
public bool useOnlinePac;
- public bool secureLocalPac;
+ public bool secureLocalPac; // enable secret for PAC server
+ public bool regeneratePacOnUpdate; // regenerate pac.txt on version update
public bool availabilityStatistics;
public bool autoCheckUpdate;
public bool checkPreRelease;
@@ -54,7 +56,7 @@ namespace Shadowsocks.Model
public HotkeyConfig hotkey;
[JsonIgnore]
- public bool updated;
+ public bool firstRunOnNewVersion;
public Configuration()
{
@@ -64,13 +66,14 @@ namespace Shadowsocks.Model
global = false;
enabled = false;
shareOverLan = false;
- isDefault = true;
+ firstRun = true;
localPort = 1080;
portableMode = true;
showPluginOutput = false;
pacUrl = "";
useOnlinePac = false;
secureLocalPac = true;
+ regeneratePacOnUpdate = true;
availabilityStatistics = false;
autoCheckUpdate = false;
checkPreRelease = false;
@@ -88,7 +91,7 @@ namespace Shadowsocks.Model
proxy = new ProxyConfig();
hotkey = new HotkeyConfig();
- updated = false;
+ firstRunOnNewVersion = false;
configs = new List();
onlineConfigSource = new List();
@@ -108,11 +111,8 @@ namespace Shadowsocks.Model
#endif
[JsonIgnore]
- public string localHost => GetLocalHost();
- private string GetLocalHost()
- {
- return isIPv6Enabled ? "[::1]" : "127.0.0.1";
- }
+ public string LocalHost => isIPv6Enabled ? "[::1]" : "127.0.0.1";
+
public Server GetCurrentServer()
{
if (index >= 0 && index < configs.Count)
@@ -129,6 +129,11 @@ namespace Shadowsocks.Model
localPort)
: null;
+ ///
+ /// Used by multiple forms to validate a server.
+ /// Communication is done by throwing exceptions.
+ ///
+ ///
public static void CheckServer(Server server)
{
CheckServer(server.server);
@@ -137,53 +142,71 @@ namespace Shadowsocks.Model
CheckTimeout(server.timeout, Server.MaxServerTimeoutSec);
}
- public static bool ChecksServer(Server server)
- {
- try
- {
- CheckServer(server);
- return true;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
+ ///
+ /// Loads the configuration from file.
+ ///
+ /// An Configuration object.
public static Configuration Load()
{
Configuration config;
- try
+ if (File.Exists(CONFIG_FILE))
{
- string configContent = File.ReadAllText(CONFIG_FILE);
- config = JsonConvert.DeserializeObject(configContent);
- config.isDefault = false;
- config.version = UpdateChecker.Version;
- if (UpdateChecker.Asset.CompareVersion(UpdateChecker.Version, config.version ?? "0") > 0)
+ try
{
- config.updated = true;
+ string configContent = File.ReadAllText(CONFIG_FILE);
+ config = JsonConvert.DeserializeObject(configContent);
+ return config;
}
-
- if (config.configs.Count == 0)
- config.configs.Add(GetDefaultServer());
- if (config.index == -1 && string.IsNullOrEmpty(config.strategy))
- config.index = 0;
- if (!System.Net.Sockets.Socket.OSSupportsIPv6)
+ catch (Exception e)
{
- config.isIPv6Enabled = false; // disable IPv6 if os not support
+ if (!(e is FileNotFoundException))
+ logger.LogUsefulException(e);
}
- //TODO if remote host(server) do not support IPv6 (or DNS resolve AAAA TYPE record) disable IPv6?
+ }
+ config = new Configuration();
+ return config;
+ }
- config.proxy.CheckConfig();
+ ///
+ /// Process the loaded configurations and set up things.
+ ///
+ /// A reference of Configuration object.
+ public static void Process(ref Configuration config)
+ {
+ // Verify if the configured geosite group exists.
+ // Reset to default if no such group.
+ if (!GeositeUpdater.CheckGeositeGroup(config.geositeGroup))
+ {
+#if DEBUG
+ logger.Debug($"Current group: {config.geositeGroup}");
+ foreach (var group in GeositeUpdater.Geosites.Keys)
+ logger.Debug($"{group}");
+#endif
+ config.geositeGroup = "geolocation-!cn";
+ logger.Warn("The specified Geosite group doesn't exist. Using default group.");
}
- catch (Exception e)
+
+ // Mark the first run of a new version.
+ if (UpdateChecker.Asset.CompareVersion(UpdateChecker.Version, config.version ?? "0") > 0)
{
- if (!(e is FileNotFoundException))
- logger.LogUsefulException(e);
- config = new Configuration();
- config.configs.Add(GetDefaultServer());
+ config.firstRunOnNewVersion = true;
}
+ // Add an empty server configuration
+ if (config.configs.Count == 0)
+ config.configs.Add(GetDefaultServer());
+ // Selected server
+ if (config.index == -1 && string.IsNullOrEmpty(config.strategy))
+ config.index = 0;
+ if (config.index >= config.configs.Count)
+ config.index = config.configs.Count - 1;
+ // Check OS IPv6 support
+ if (!System.Net.Sockets.Socket.OSSupportsIPv6)
+ config.isIPv6Enabled = false;
+ config.proxy.CheckConfig();
+ // Replace $version with the version number.
+ config.userAgentString = config.userAgent.Replace("$version", config.version);
+ // NLog log level
try
{
config.nLogConfig = NLogConfig.LoadXML();
@@ -203,48 +226,42 @@ namespace Shadowsocks.Model
}
catch (Exception e)
{
- // todo: route the error to UI since there is no log file in this scenario
- logger.Error(e, "Cannot get the log level from NLog config file. Please check if the nlog config file exists with corresponding XML nodes.");
+ MessageBox.Show($"Cannot get the log level from NLog config file. Please check if the nlog config file exists with corresponding XML nodes.\n{e.Message}");
}
-
- config.userAgentString = config.userAgent.Replace("$version", config.version);
-
- return config;
}
+ ///
+ /// Saves the Configuration object to file.
+ ///
+ /// A Configuration object.
public static void Save(Configuration config)
{
config.configs = SortByOnlineConfig(config.configs);
- if (config.index >= config.configs.Count)
- config.index = config.configs.Count - 1;
- if (config.index < -1)
- config.index = -1;
- if (config.index == -1 && string.IsNullOrEmpty(config.strategy))
- config.index = 0;
- config.isDefault = false;
+
+ FileStream configFileStream = null;
+ StreamWriter configStreamWriter = null;
try
{
- using (StreamWriter sw = new StreamWriter(File.Open(CONFIG_FILE, FileMode.Create)))
- {
- string jsonString = JsonConvert.SerializeObject(config, Formatting.Indented);
- sw.Write(jsonString);
- sw.Flush();
- }
- try
- {
- // apply changes to NLog.config
- config.nLogConfig.SetLogLevel(config.isVerboseLogging ? verboseLogLevel : NLogConfig.LogLevel.Info);
- NLogConfig.SaveXML(config.nLogConfig);
- }
- catch (Exception e)
- {
- logger.Error(e, "Cannot set the log level to NLog config file. Please check if the nlog config file exists with corresponding XML nodes.");
- }
+ configFileStream = File.Open(CONFIG_FILE, FileMode.Create);
+ configStreamWriter = new StreamWriter(configFileStream);
+ var jsonString = JsonConvert.SerializeObject(config, Formatting.Indented);
+ configStreamWriter.Write(jsonString);
+ configStreamWriter.Flush();
+ // NLog
+ config.nLogConfig.SetLogLevel(config.isVerboseLogging ? verboseLogLevel : NLogConfig.LogLevel.Info);
+ NLogConfig.SaveXML(config.nLogConfig);
}
- catch (IOException e)
+ catch (Exception e)
{
logger.LogUsefulException(e);
}
+ finally
+ {
+ if (configStreamWriter != null)
+ configStreamWriter.Dispose();
+ if (configFileStream != null)
+ configFileStream.Dispose();
+ }
}
public static List SortByOnlineConfig(IEnumerable servers)
diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs
index 6da06f0f..9e266105 100755
--- a/shadowsocks-csharp/Program.cs
+++ b/shadowsocks-csharp/Program.cs
@@ -97,8 +97,6 @@ namespace Shadowsocks
#endregion
#region Event Handlers Setup
- Utils.ReleaseMemory(true);
-
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// handle UI exceptions
Application.ThreadException += Application_ThreadException;
@@ -185,7 +183,7 @@ namespace Shadowsocks
Thread.Sleep(10 * 1000);
try
{
- MainController.Start(false);
+ MainController.Start(true);
logger.Info("controller started");
}
catch (Exception ex)
diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs
index a24ce2c2..8e385680 100755
--- a/shadowsocks-csharp/Util/Util.cs
+++ b/shadowsocks-csharp/Util/Util.cs
@@ -95,42 +95,6 @@ namespace Shadowsocks.Util
return Path.Combine(GetTempPath(), filename);
}
- public static void ReleaseMemory(bool removePages)
- {
- // release any unused pages
- // making the numbers look good in task manager
- // this is totally nonsense in programming
- // but good for those users who care
- // making them happier with their everyday life
- // which is part of user experience
- GC.Collect(GC.MaxGeneration);
- GC.WaitForPendingFinalizers();
- if (removePages)
- {
- // as some users have pointed out
- // removing pages from working set will cause some IO
- // which lowered user experience for another group of users
- //
- // so we do 2 more things here to satisfy them:
- // 1. only remove pages once when configuration is changed
- // 2. add more comments here to tell users that calling
- // this function will not be more frequent than
- // IM apps writing chat logs, or web browsers writing cache files
- // if they're so concerned about their disk, they should
- // uninstall all IM apps and web browsers
- //
- // please open an issue if you're worried about anything else in your computer
- // no matter it's GPU performance, monitor contrast, audio fidelity
- // or anything else in the task manager
- // we'll do as much as we can to help you
- //
- // just kidding
- SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
- (UIntPtr)0xFFFFFFFF,
- (UIntPtr)0xFFFFFFFF);
- }
- }
-
public static string UnGzip(byte[] buf)
{
byte[] buffer = new byte[1024];
diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs
index 8bcd6d9c..1da2ef9b 100644
--- a/shadowsocks-csharp/View/MenuViewController.cs
+++ b/shadowsocks-csharp/View/MenuViewController.cs
@@ -29,7 +29,6 @@ namespace Shadowsocks.View
private NotifyIcon _notifyIcon;
private Icon icon, icon_in, icon_out, icon_both, previousIcon;
- private bool _isFirstRun;
private bool _isStartupChecking;
private string _urlToOpen;
@@ -50,6 +49,7 @@ namespace Shadowsocks.View
private MenuItem editGFWUserRuleItem;
private MenuItem editOnlinePACItem;
private MenuItem secureLocalPacUrlToggleItem;
+ private MenuItem regenerateLocalPacOnUpdateItem;
private MenuItem autoCheckUpdatesToggleItem;
private MenuItem checkPreReleaseToggleItem;
private MenuItem proxyItem;
@@ -108,9 +108,8 @@ namespace Shadowsocks.View
Configuration config = controller.GetConfigurationCopy();
- if (config.isDefault)
+ if (config.firstRun)
{
- _isFirstRun = true;
ShowConfigForm();
}
else if (config.autoCheckUpdate)
@@ -279,6 +278,7 @@ namespace Shadowsocks.View
this.updateFromGeositeItem = CreateMenuItem("Update Local PAC from Geosite", new EventHandler(this.UpdatePACFromGeositeItem_Click)),
this.editGFWUserRuleItem = CreateMenuItem("Edit User Rule for Geosite...", new EventHandler(this.EditUserRuleFileForGeositeItem_Click)),
this.secureLocalPacUrlToggleItem = CreateMenuItem("Secure Local PAC", new EventHandler(this.SecureLocalPacUrlToggleItem_Click)),
+ this.regenerateLocalPacOnUpdateItem = CreateMenuItem("Regenerate local PAC on version update", new EventHandler(this.RegenerateLocalPacOnUpdateItem_Click)),
CreateMenuItem("Copy Local PAC URL", new EventHandler(this.CopyLocalPacUrlItem_Click)),
this.editOnlinePACItem = CreateMenuItem("Edit Online PAC URL...", new EventHandler(this.UpdateOnlinePACURLItem_Click)),
}),
@@ -336,7 +336,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(), I18N.GetString("Shadowsocks Error: {0}", e.GetException().Message));
}
@@ -360,6 +360,7 @@ namespace Shadowsocks.View
onlinePACItem.Checked = onlinePACItem.Enabled && config.useOnlinePac;
localPACItem.Checked = !onlinePACItem.Checked;
secureLocalPacUrlToggleItem.Checked = config.secureLocalPac;
+ regenerateLocalPacOnUpdateItem.Checked = config.regeneratePacOnUpdate;
UpdatePACItemsEnabledStatus();
UpdateUpdateMenu();
}
@@ -446,15 +447,14 @@ namespace Shadowsocks.View
{
logForm.Dispose();
logForm = null;
- Utils.ReleaseMemory(true);
}
void configForm_FormClosed(object sender, FormClosedEventArgs e)
{
configForm.Dispose();
configForm = null;
- Utils.ReleaseMemory(true);
- if (_isFirstRun)
+ var config = controller.GetCurrentConfiguration();
+ if (config.firstRun)
{
CheckUpdateForFirstRun();
ShowBalloonTip(
@@ -463,7 +463,7 @@ namespace Shadowsocks.View
ToolTipIcon.Info,
0
);
- _isFirstRun = false;
+ config.firstRun = false;
}
}
@@ -471,21 +471,18 @@ namespace Shadowsocks.View
{
proxyForm.Dispose();
proxyForm = null;
- Utils.ReleaseMemory(true);
}
void hotkeySettingsForm_FormClosed(object sender, FormClosedEventArgs e)
{
hotkeySettingsForm.Dispose();
hotkeySettingsForm = null;
- Utils.ReleaseMemory(true);
}
void onlineConfigForm_FormClosed(object sender, FormClosedEventArgs e)
{
onlineConfigForm.Dispose();
onlineConfigForm = null;
- Utils.ReleaseMemory(true);
}
#endregion
@@ -541,7 +538,8 @@ namespace Shadowsocks.View
private void CheckUpdateForFirstRun()
{
Configuration config = controller.GetConfigurationCopy();
- if (config.isDefault) return;
+ if (config.firstRun)
+ return;
_isStartupChecking = true;
updateChecker.CheckUpdate(config, 3000);
}
@@ -689,14 +687,18 @@ namespace Shadowsocks.View
Configuration configuration = controller.GetConfigurationCopy();
foreach (var server in configuration.configs)
{
- if (Configuration.ChecksServer(server))
+ try
{
+ Configuration.CheckServer(server);
MenuItem item = new MenuItem(server.ToString());
item.Tag = configuration.configs.FindIndex(s => s == server);
item.Click += AServerItem_Click;
items.Add(strategyCount + serverCount, item);
serverCount++;
}
+ catch
+ {
+ }
}
foreach (MenuItem item in items)
@@ -901,6 +903,12 @@ namespace Shadowsocks.View
controller.ToggleSecureLocalPac(!configuration.secureLocalPac);
}
+ private void RegenerateLocalPacOnUpdateItem_Click(object sender, EventArgs e)
+ {
+ var config = controller.GetConfigurationCopy();
+ controller.ToggleRegeneratePacOnUpdate(!config.regeneratePacOnUpdate);
+ }
+
private void CopyLocalPacUrlItem_Click(object sender, EventArgs e)
{
controller.CopyPacUrl();
diff --git a/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs b/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs
index 24e4096e..1ed4d785 100644
--- a/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs
+++ b/shadowsocks-csharp/ViewModels/ServerSharingViewModel.cs
@@ -16,7 +16,7 @@ namespace Shadowsocks.ViewModels
///
public ServerSharingViewModel()
{
- _config = Configuration.Load();
+ _config = Program.MainController.GetCurrentConfiguration();
_servers = _config.configs;
_selectedServer = _servers.First();
//_selectedServerUrlImage = new BitmapImage();