# Conflicts: # README.md # shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs # shadowsocks-csharp/Controller/Service/PACServer.cs # shadowsocks-csharp/Controller/Strategy/SimplyChooseByStatisticsStrategy.cs # shadowsocks-csharp/Data/cn.txt # shadowsocks-csharp/Model/Configuration.cs # shadowsocks-csharp/Model/LogViewerConfig.cs # shadowsocks-csharp/View/LogForm.Designer.cs # shadowsocks-csharp/View/LogForm.cs # shadowsocks-csharp/View/MenuViewController.cstags/3.0
@@ -32,11 +32,20 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
public static void Debug(object o) | |||||
public static void Error(object o) | |||||
{ | { | ||||
Console.WriteLine("[E] "+ o); | |||||
} | |||||
#if DEBUG | |||||
public static void Info(object o) | |||||
{ | |||||
Console.WriteLine(o); | Console.WriteLine(o); | ||||
} | |||||
public static void Debug(object o) | |||||
{ | |||||
#if DEBUG | |||||
Console.WriteLine("[D] " + o); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -126,8 +126,7 @@ namespace Shadowsocks.Controller | |||||
var IP = Dns.GetHostAddresses(server.server).First(ip => (ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6)); | var IP = Dns.GetHostAddresses(server.server).First(ip => (ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6)); | ||||
var ping = new Ping(); | var ping = new Ping(); | ||||
var ret = new List<DataList>(); | var ret = new List<DataList>(); | ||||
foreach ( | |||||
var timestamp in Enumerable.Range(0, Repeat).Select(_ => DateTime.Now.ToString(DateTimePattern))) | |||||
foreach (var timestamp in Enumerable.Range(0, Repeat).Select(_ => DateTime.Now.ToString(DateTimePattern))) | |||||
{ | { | ||||
//ICMP echo. we can also set options and special bytes | //ICMP echo. we can also set options and special bytes | ||||
try | try | ||||
@@ -146,7 +145,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine($"An exception occured when eveluating {server.FriendlyName()}"); | |||||
Logging.Error($"An exception occured while eveluating {server.FriendlyName()}"); | |||||
Logging.LogUsefulException(e); | Logging.LogUsefulException(e); | ||||
} | } | ||||
} | } | ||||
@@ -38,6 +38,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
File.WriteAllText(Utils.GetTempPath() + "\\gfwlist.txt", e.Result, Encoding.UTF8); | |||||
List<string> lines = ParseResult(e.Result); | List<string> lines = ParseResult(e.Result); | ||||
if (File.Exists(USER_RULE_FILE)) | if (File.Exists(USER_RULE_FILE)) | ||||
{ | { | ||||
@@ -92,7 +93,7 @@ namespace Shadowsocks.Controller | |||||
http.DownloadStringAsync(new Uri(GFWLIST_URL)); | http.DownloadStringAsync(new Uri(GFWLIST_URL)); | ||||
} | } | ||||
public List<string> ParseResult(string response) | |||||
public static List<string> ParseResult(string response) | |||||
{ | { | ||||
byte[] bytes = Convert.FromBase64String(response); | byte[] bytes = Convert.FromBase64String(response); | ||||
string content = Encoding.ASCII.GetString(bytes); | string content = Encoding.ASCII.GetString(bytes); | ||||
@@ -78,7 +78,7 @@ namespace Shadowsocks.Controller | |||||
_tcpSocket.Listen(1024); | _tcpSocket.Listen(1024); | ||||
// Start an asynchronous socket to listen for connections. | // Start an asynchronous socket to listen for connections. | ||||
Console.WriteLine("Shadowsocks started"); | |||||
Logging.Info("Shadowsocks started"); | |||||
_tcpSocket.BeginAccept( | _tcpSocket.BeginAccept( | ||||
new AsyncCallback(AcceptCallback), | new AsyncCallback(AcceptCallback), | ||||
_tcpSocket); | _tcpSocket); | ||||
@@ -163,7 +163,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e); | |||||
Logging.LogUsefulException(e); | |||||
} | } | ||||
finally | finally | ||||
{ | { | ||||
@@ -208,7 +208,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e); | |||||
Logging.LogUsefulException(e); | |||||
conn.Close(); | conn.Close(); | ||||
} | } | ||||
} | } | ||||
@@ -2,6 +2,7 @@ | |||||
using Shadowsocks.Properties; | using Shadowsocks.Properties; | ||||
using Shadowsocks.Util; | using Shadowsocks.Util; | ||||
using System; | using System; | ||||
using System.Collections; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Diagnostics; | using System.Diagnostics; | ||||
using System.IO; | using System.IO; | ||||
@@ -15,19 +16,20 @@ namespace Shadowsocks.Controller | |||||
class PACServer : Listener.Service | class PACServer : Listener.Service | ||||
{ | { | ||||
public static string PAC_FILE = "pac.txt"; | public static string PAC_FILE = "pac.txt"; | ||||
public static string USER_RULE_FILE = "user-rule.txt"; | public static string USER_RULE_FILE = "user-rule.txt"; | ||||
public static string USER_ABP_FILE = "abp.txt"; | public static string USER_ABP_FILE = "abp.txt"; | ||||
FileSystemWatcher watcher; | |||||
FileSystemWatcher PACFileWatcher; | |||||
FileSystemWatcher UserRuleFileWatcher; | |||||
private Configuration _config; | private Configuration _config; | ||||
public event EventHandler PACFileChanged; | public event EventHandler PACFileChanged; | ||||
public event EventHandler UserRuleFileChanged; | |||||
public PACServer() | public PACServer() | ||||
{ | { | ||||
this.WatchPacFile(); | this.WatchPacFile(); | ||||
this.WatchUserRuleFile(); | |||||
} | } | ||||
public void UpdateConfiguration(Configuration config) | public void UpdateConfiguration(Configuration config) | ||||
@@ -151,7 +153,7 @@ Connection: Close | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e); | |||||
Logging.LogUsefulException(e); | |||||
socket.Close(); | socket.Close(); | ||||
} | } | ||||
} | } | ||||
@@ -169,28 +171,81 @@ Connection: Close | |||||
private void WatchPacFile() | private void WatchPacFile() | ||||
{ | { | ||||
if (watcher != null) | |||||
{ | |||||
watcher.Dispose(); | |||||
} | |||||
watcher = new FileSystemWatcher(Directory.GetCurrentDirectory()); | |||||
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; | |||||
watcher.Filter = PAC_FILE; | |||||
watcher.Changed += Watcher_Changed; | |||||
watcher.Created += Watcher_Changed; | |||||
watcher.Deleted += Watcher_Changed; | |||||
watcher.Renamed += Watcher_Changed; | |||||
watcher.EnableRaisingEvents = true; | |||||
if (PACFileWatcher != null) | |||||
{ | |||||
PACFileWatcher.Dispose(); | |||||
} | |||||
PACFileWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory()); | |||||
PACFileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; | |||||
PACFileWatcher.Filter = PAC_FILE; | |||||
PACFileWatcher.Changed += PACFileWatcher_Changed; | |||||
PACFileWatcher.Created += PACFileWatcher_Changed; | |||||
PACFileWatcher.Deleted += PACFileWatcher_Changed; | |||||
PACFileWatcher.Renamed += PACFileWatcher_Changed; | |||||
PACFileWatcher.EnableRaisingEvents = true; | |||||
} | |||||
private void WatchUserRuleFile() | |||||
{ | |||||
if (UserRuleFileWatcher != null) | |||||
{ | |||||
UserRuleFileWatcher.Dispose(); | |||||
} | |||||
UserRuleFileWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory()); | |||||
UserRuleFileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; | |||||
UserRuleFileWatcher.Filter = USER_RULE_FILE; | |||||
UserRuleFileWatcher.Changed += UserRuleFileWatcher_Changed; | |||||
UserRuleFileWatcher.Created += UserRuleFileWatcher_Changed; | |||||
UserRuleFileWatcher.Deleted += UserRuleFileWatcher_Changed; | |||||
UserRuleFileWatcher.Renamed += UserRuleFileWatcher_Changed; | |||||
UserRuleFileWatcher.EnableRaisingEvents = true; | |||||
} | |||||
#region FileSystemWatcher.OnChanged() | |||||
// FileSystemWatcher Changed event is raised twice | |||||
// http://stackoverflow.com/questions/1764809/filesystemwatcher-changed-event-is-raised-twice | |||||
private static Hashtable fileChangedTime = new Hashtable(); | |||||
private void PACFileWatcher_Changed(object sender, FileSystemEventArgs e) | |||||
{ | |||||
string path = e.FullPath.ToString(); | |||||
string currentLastWriteTime = File.GetLastWriteTime(e.FullPath).ToString(); | |||||
// if there is no path info stored yet or stored path has different time of write then the one now is inspected | |||||
if (!fileChangedTime.ContainsKey(path) || fileChangedTime[path].ToString() != currentLastWriteTime) | |||||
{ | |||||
if (PACFileChanged != null) | |||||
{ | |||||
Logging.Info($"Detected: PAC file '{e.Name}' was {e.ChangeType.ToString().ToLower()}."); | |||||
PACFileChanged(this, new EventArgs()); | |||||
} | |||||
//lastly we update the last write time in the hashtable | |||||
fileChangedTime[path] = currentLastWriteTime; | |||||
} | |||||
} | } | ||||
private void Watcher_Changed(object sender, FileSystemEventArgs e) | |||||
private void UserRuleFileWatcher_Changed(object sender, FileSystemEventArgs e) | |||||
{ | { | ||||
if (PACFileChanged != null) | |||||
string path = e.FullPath.ToString(); | |||||
string currentLastWriteTime = File.GetLastWriteTime(e.FullPath).ToString(); | |||||
// if there is no path info stored yet or stored path has different time of write then the one now is inspected | |||||
if (!fileChangedTime.ContainsKey(path) || fileChangedTime[path].ToString() != currentLastWriteTime) | |||||
{ | { | ||||
PACFileChanged(this, new EventArgs()); | |||||
if (UserRuleFileChanged != null) | |||||
{ | |||||
Logging.Info($"Detected: User Rule file '{e.Name}' was {e.ChangeType.ToString().ToLower()}."); | |||||
UserRuleFileChanged(this, new EventArgs()); | |||||
} | |||||
//lastly we update the last write time in the hashtable | |||||
fileChangedTime[path] = currentLastWriteTime; | |||||
} | } | ||||
} | } | ||||
#endregion | |||||
private string GetPACAddress(byte[] requestBuf, int length, IPEndPoint localEndPoint, bool useSocks) | private string GetPACAddress(byte[] requestBuf, int length, IPEndPoint localEndPoint, bool useSocks) | ||||
{ | { | ||||
//try | //try | ||||
@@ -204,7 +259,7 @@ Connection: Close | |||||
//} | //} | ||||
//catch (Exception e) | //catch (Exception e) | ||||
//{ | //{ | ||||
// Console.WriteLine(e); | |||||
// Logging.LogUsefulException(e); | |||||
//} | //} | ||||
return (useSocks ? "SOCKS5 " : "PROXY ") + localEndPoint.Address + ":" + this._config.localPort + ";"; | return (useSocks ? "SOCKS5 " : "PROXY ") + localEndPoint.Address + ":" + this._config.localPort + ";"; | ||||
} | } | ||||
@@ -56,7 +56,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e.ToString()); | |||||
Logging.LogUsefulException(e); | |||||
} | } | ||||
} | } | ||||
string polipoConfig = Resources.privoxy_conf; | string polipoConfig = Resources.privoxy_conf; | ||||
@@ -94,7 +94,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e.ToString()); | |||||
Logging.LogUsefulException(e); | |||||
} | } | ||||
_process = null; | _process = null; | ||||
} | } | ||||
@@ -140,7 +140,6 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
//Console.WriteLine("bytesRead: " + bytesRead.ToString()); | |||||
_local.Shutdown(SocketShutdown.Send); | _local.Shutdown(SocketShutdown.Send); | ||||
_localShutdown = true; | _localShutdown = true; | ||||
CheckClose(); | CheckClose(); | ||||
@@ -49,7 +49,7 @@ namespace Shadowsocks.Controller | |||||
lock (this.Handlers) | lock (this.Handlers) | ||||
{ | { | ||||
this.Handlers.Add(handler); | this.Handlers.Add(handler); | ||||
Logging.Debug($"connections: {Handlers.Count}"); | |||||
Logging.Debug($"TCP connections: {Handlers.Count}"); | |||||
DateTime now = DateTime.Now; | DateTime now = DateTime.Now; | ||||
if (now - _lastSweepTime > TimeSpan.FromSeconds(1)) | if (now - _lastSweepTime > TimeSpan.FromSeconds(1)) | ||||
{ | { | ||||
@@ -65,10 +65,10 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
foreach (Handler handler1 in handlersToClose) | foreach (Handler handler1 in handlersToClose) | ||||
{ | { | ||||
Logging.Debug("Closing timed out connection"); | |||||
Logging.Debug("Closing timed out TCP connection."); | |||||
handler1.Close(); | handler1.Close(); | ||||
} | } | ||||
return true; | |||||
return true; | |||||
} | } | ||||
} | } | ||||
@@ -149,7 +149,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
lock (relay.Handlers) | lock (relay.Handlers) | ||||
{ | { | ||||
Logging.Debug($"connections: {relay.Handlers.Count}"); | |||||
Logging.Debug($"TCP connections: {relay.Handlers.Count}"); | |||||
relay.Handlers.Remove(this); | relay.Handlers.Remove(this); | ||||
} | } | ||||
lock (this) | lock (this) | ||||
@@ -213,7 +213,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
// reject socks 4 | // reject socks 4 | ||||
response = new byte[] { 0, 91 }; | response = new byte[] { 0, 91 }; | ||||
Console.WriteLine("socks 5 protocol error"); | |||||
Logging.Error("socks 5 protocol error"); | |||||
} | } | ||||
Logging.Debug($"======Send Local Port, size:" + response.Length); | Logging.Debug($"======Send Local Port, size:" + response.Length); | ||||
connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null); | connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null); | ||||
@@ -284,7 +284,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
Console.WriteLine("failed to recv data in handshakeReceive2Callback"); | |||||
Logging.Error("failed to recv data in handshakeReceive2Callback"); | |||||
this.Close(); | this.Close(); | ||||
} | } | ||||
} | } | ||||
@@ -431,7 +431,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
strategy.SetFailure(server); | strategy.SetFailure(server); | ||||
} | } | ||||
Console.WriteLine(String.Format("{0} timed out", server.FriendlyName())); | |||||
Logging.Info($"{server.FriendlyName()} timed out"); | |||||
remote.Close(); | remote.Close(); | ||||
RetryConnect(); | RetryConnect(); | ||||
} | } | ||||
@@ -470,8 +470,7 @@ namespace Shadowsocks.Controller | |||||
connected = true; | connected = true; | ||||
//Console.WriteLine("Socket connected to {0}", | |||||
// remote.RemoteEndPoint.ToString()); | |||||
Logging.Debug($"Socket connected to {remote.RemoteEndPoint}"); | |||||
var latency = DateTime.Now - _startConnectTime; | var latency = DateTime.Now - _startConnectTime; | ||||
IStrategy strategy = controller.GetCurrentStrategy(); | IStrategy strategy = controller.GetCurrentStrategy(); | ||||
@@ -556,7 +555,6 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
//Console.WriteLine("bytesRead: " + bytesRead.ToString()); | |||||
connection.Shutdown(SocketShutdown.Send); | connection.Shutdown(SocketShutdown.Send); | ||||
connectionShutdown = true; | connectionShutdown = true; | ||||
CheckClose(); | CheckClose(); | ||||
@@ -7,6 +7,8 @@ using System.Threading; | |||||
using System.Net.Sockets; | using System.Net.Sockets; | ||||
using Shadowsocks.Controller.Strategy; | using Shadowsocks.Controller.Strategy; | ||||
using System.Net; | using System.Net; | ||||
using Shadowsocks.Util; | |||||
using Shadowsocks.Properties; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -314,6 +316,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
_pacServer = new PACServer(); | _pacServer = new PACServer(); | ||||
_pacServer.PACFileChanged += pacServer_PACFileChanged; | _pacServer.PACFileChanged += pacServer_PACFileChanged; | ||||
_pacServer.UserRuleFileChanged += pacServer_UserRuleFileChanged; | |||||
} | } | ||||
_pacServer.UpdateConfiguration(_config); | _pacServer.UpdateConfiguration(_config); | ||||
if (gfwListUpdater == null) | if (gfwListUpdater == null) | ||||
@@ -424,6 +427,39 @@ namespace Shadowsocks.Controller | |||||
UpdatePACFromGFWListError(this, e); | UpdatePACFromGFWListError(this, e); | ||||
} | } | ||||
private void pacServer_UserRuleFileChanged(object sender, EventArgs e) | |||||
{ | |||||
// TODO: this is a dirty hack. (from code GListUpdater.http_DownloadStringCompleted()) | |||||
if (!File.Exists(Utils.GetTempPath() + "\\gfwlist.txt")) | |||||
{ | |||||
UpdatePACFromGFWList(); | |||||
return; | |||||
} | |||||
List<string> lines = GFWListUpdater.ParseResult(File.ReadAllText(Utils.GetTempPath() + "\\gfwlist.txt")); | |||||
if (File.Exists(PACServer.USER_RULE_FILE)) | |||||
{ | |||||
string local = File.ReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8); | |||||
string[] rules = local.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); | |||||
foreach (string rule in rules) | |||||
{ | |||||
if (rule.StartsWith("!") || rule.StartsWith("[")) | |||||
continue; | |||||
lines.Add(rule); | |||||
} | |||||
} | |||||
string abpContent = Utils.UnGzip(Resources.abp_js); | |||||
abpContent = abpContent.Replace("__RULES__", SimpleJson.SimpleJson.SerializeObject(lines)); | |||||
if (File.Exists(PACServer.PAC_FILE)) | |||||
{ | |||||
string original = File.ReadAllText(PACServer.PAC_FILE, Encoding.UTF8); | |||||
if (original == abpContent) | |||||
{ | |||||
return; | |||||
} | |||||
} | |||||
File.WriteAllText(PACServer.PAC_FILE, abpContent, Encoding.UTF8); | |||||
} | |||||
private void StartReleasingMemory() | private void StartReleasingMemory() | ||||
{ | { | ||||
_ramThread = new Thread(new ThreadStart(ReleaseMemory)); | _ramThread = new Thread(new ThreadStart(ReleaseMemory)); | ||||
@@ -132,14 +132,14 @@ namespace Shadowsocks.Controller.Strategy | |||||
if (_currentServer == null || max.score - _currentServer.score > 200) | if (_currentServer == null || max.score - _currentServer.score > 200) | ||||
{ | { | ||||
_currentServer = max; | _currentServer = max; | ||||
Console.WriteLine("HA switching to server: {0}", _currentServer.server.FriendlyName()); | |||||
Logging.Info($"HA switching to server: {_currentServer.server.FriendlyName()}"); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
public void UpdateLatency(Model.Server server, TimeSpan latency) | public void UpdateLatency(Model.Server server, TimeSpan latency) | ||||
{ | { | ||||
Logging.Debug(String.Format("latency: {0} {1}", server.FriendlyName(), latency)); | |||||
Logging.Debug($"latency: {server.FriendlyName()} {latency}"); | |||||
ServerStatus status; | ServerStatus status; | ||||
if (_serverStatus.TryGetValue(server, out status)) | if (_serverStatus.TryGetValue(server, out status)) | ||||
@@ -151,7 +151,7 @@ namespace Shadowsocks.Controller.Strategy | |||||
public void UpdateLastRead(Model.Server server) | public void UpdateLastRead(Model.Server server) | ||||
{ | { | ||||
Logging.Debug(String.Format("last read: {0}", server.FriendlyName())); | |||||
Logging.Debug($"last read: {server.FriendlyName()}"); | |||||
ServerStatus status; | ServerStatus status; | ||||
if (_serverStatus.TryGetValue(server, out status)) | if (_serverStatus.TryGetValue(server, out status)) | ||||
@@ -162,7 +162,7 @@ namespace Shadowsocks.Controller.Strategy | |||||
public void UpdateLastWrite(Model.Server server) | public void UpdateLastWrite(Model.Server server) | ||||
{ | { | ||||
Logging.Debug(String.Format("last write: {0}", server.FriendlyName())); | |||||
Logging.Debug($"last write: {server.FriendlyName()}"); | |||||
ServerStatus status; | ServerStatus status; | ||||
if (_serverStatus.TryGetValue(server, out status)) | if (_serverStatus.TryGetValue(server, out status)) | ||||
@@ -173,7 +173,7 @@ namespace Shadowsocks.Controller.Strategy | |||||
public void SetFailure(Model.Server server) | public void SetFailure(Model.Server server) | ||||
{ | { | ||||
Logging.Debug(String.Format("failure: {0}", server.FriendlyName())); | |||||
Logging.Debug($"failure: {server.FriendlyName()}"); | |||||
ServerStatus status; | ServerStatus status; | ||||
if (_serverStatus.TryGetValue(server, out status)) | if (_serverStatus.TryGetValue(server, out status)) | ||||
@@ -30,7 +30,7 @@ namespace Shadowsocks.Encryption | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e.ToString()); | |||||
Logging.LogUsefulException(e); | |||||
} | } | ||||
LoadLibrary(dllPath); | LoadLibrary(dllPath); | ||||
} | } | ||||
@@ -26,7 +26,7 @@ namespace Shadowsocks.Encryption | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Console.WriteLine(e.ToString()); | |||||
Logging.LogUsefulException(e); | |||||
} | } | ||||
LoadLibrary(dllPath); | LoadLibrary(dllPath); | ||||
} | } | ||||
@@ -72,7 +72,7 @@ namespace Shadowsocks.Model | |||||
{ | { | ||||
if (!(e is FileNotFoundException)) | if (!(e is FileNotFoundException)) | ||||
{ | { | ||||
Console.WriteLine(e); | |||||
Logging.LogUsefulException(e); | |||||
} | } | ||||
return new Configuration | return new Configuration | ||||
{ | { | ||||
@@ -167,6 +167,7 @@ namespace Shadowsocks.Model | |||||
} | } | ||||
} | } | ||||
// internal class | |||||
private class JsonSerializerStrategy : SimpleJson.PocoJsonSerializerStrategy | private class JsonSerializerStrategy : SimpleJson.PocoJsonSerializerStrategy | ||||
{ | { | ||||
// convert string to int | // convert string to int | ||||
@@ -1,5 +1,7 @@ | |||||
using System; | |||||
using Shadowsocks.View; | |||||
using System; | |||||
using System.Drawing; | using System.Drawing; | ||||
using System.Windows.Forms; | |||||
namespace Shadowsocks.Model | namespace Shadowsocks.Model | ||||
{ | { | ||||
@@ -13,16 +15,37 @@ namespace Shadowsocks.Model | |||||
public bool topMost; | public bool topMost; | ||||
public bool wrapText; | public bool wrapText; | ||||
public bool toolbarShown; | public bool toolbarShown; | ||||
public int width; | |||||
public int height; | |||||
public int top; | |||||
public int left; | |||||
public LogViewerConfig() | public LogViewerConfig() | ||||
{ | { | ||||
this.fontName = "Consolas"; | |||||
this.fontSize = 8; | |||||
this.bgColor = "black"; | |||||
this.textColor = "white"; | |||||
this.topMost = false; | |||||
this.wrapText = false; | |||||
this.toolbarShown = false; | |||||
fontName = "Consolas"; | |||||
fontSize = 8; | |||||
bgColor = "black"; | |||||
textColor = "white"; | |||||
topMost = false; | |||||
wrapText = false; | |||||
toolbarShown = false; | |||||
width = 600; | |||||
height = 400; | |||||
left = GetBestLeft(); | |||||
top = GetBestTop(); | |||||
} | |||||
// Use GetBestTop() and GetBestLeft() to ensure the log viwer form can be always display IN screen. | |||||
public int GetBestLeft() | |||||
{ | |||||
width = (width >= 400) ? width : 400; // set up the minimum size | |||||
return Screen.PrimaryScreen.WorkingArea.Width - width; | |||||
} | |||||
public int GetBestTop() | |||||
{ | |||||
height = (height >= 200) ? height : 200; // set up the minimum size | |||||
return Screen.PrimaryScreen.WorkingArea.Height - height; | |||||
} | } | ||||
public Font GetFont() | public Font GetFont() | ||||
@@ -7,6 +7,8 @@ using System.Runtime.InteropServices; | |||||
using System.Text; | using System.Text; | ||||
using System.Windows.Forms; | using System.Windows.Forms; | ||||
using Shadowsocks.Controller; | |||||
namespace Shadowsocks.Util | namespace Shadowsocks.Util | ||||
{ | { | ||||
public class Utils | public class Utils | ||||
@@ -19,9 +21,10 @@ namespace Shadowsocks.Util | |||||
try | try | ||||
{ | { | ||||
Directory.CreateDirectory(Application.StartupPath + "\\temp"); | Directory.CreateDirectory(Application.StartupPath + "\\temp"); | ||||
} catch (Exception e) | |||||
} | |||||
catch (Exception e) | |||||
{ | { | ||||
Console.WriteLine(e); | |||||
Logging.LogUsefulException(e); | |||||
} | } | ||||
// don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log | // don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log | ||||
return Application.StartupPath + "\\temp"; | return Application.StartupPath + "\\temp"; | ||||
@@ -63,7 +63,7 @@ | |||||
this.LogMessageTextBox.Name = "LogMessageTextBox"; | this.LogMessageTextBox.Name = "LogMessageTextBox"; | ||||
this.LogMessageTextBox.ReadOnly = true; | this.LogMessageTextBox.ReadOnly = true; | ||||
this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; | this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; | ||||
this.LogMessageTextBox.Size = new System.Drawing.Size(584, 377); | |||||
this.LogMessageTextBox.Size = new System.Drawing.Size(378, 99); | |||||
this.LogMessageTextBox.TabIndex = 0; | this.LogMessageTextBox.TabIndex = 0; | ||||
// | // | ||||
// MainMenu | // MainMenu | ||||
@@ -141,7 +141,7 @@ | |||||
// | // | ||||
// TopMostCheckBox | // TopMostCheckBox | ||||
// | // | ||||
this.TopMostCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||||
this.TopMostCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||||
| System.Windows.Forms.AnchorStyles.Left))); | | System.Windows.Forms.AnchorStyles.Left))); | ||||
this.TopMostCheckBox.AutoSize = true; | this.TopMostCheckBox.AutoSize = true; | ||||
this.TopMostCheckBox.Location = new System.Drawing.Point(249, 3); | this.TopMostCheckBox.Location = new System.Drawing.Point(249, 3); | ||||
@@ -176,7 +176,7 @@ | |||||
// | // | ||||
// WrapTextCheckBox | // WrapTextCheckBox | ||||
// | // | ||||
this.WrapTextCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||||
this.WrapTextCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||||
| System.Windows.Forms.AnchorStyles.Left))); | | System.Windows.Forms.AnchorStyles.Left))); | ||||
this.WrapTextCheckBox.AutoSize = true; | this.WrapTextCheckBox.AutoSize = true; | ||||
this.WrapTextCheckBox.Location = new System.Drawing.Point(165, 3); | this.WrapTextCheckBox.Location = new System.Drawing.Point(165, 3); | ||||
@@ -199,7 +199,7 @@ | |||||
this.tableLayoutPanel1.RowCount = 2; | this.tableLayoutPanel1.RowCount = 2; | ||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | ||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(590, 418); | |||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(384, 140); | |||||
this.tableLayoutPanel1.TabIndex = 2; | this.tableLayoutPanel1.TabIndex = 2; | ||||
// | // | ||||
// ToolbarFlowLayoutPanel | // ToolbarFlowLayoutPanel | ||||
@@ -212,16 +212,17 @@ | |||||
this.ToolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; | this.ToolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; | ||||
this.ToolbarFlowLayoutPanel.Location = new System.Drawing.Point(3, 3); | this.ToolbarFlowLayoutPanel.Location = new System.Drawing.Point(3, 3); | ||||
this.ToolbarFlowLayoutPanel.Name = "ToolbarFlowLayoutPanel"; | this.ToolbarFlowLayoutPanel.Name = "ToolbarFlowLayoutPanel"; | ||||
this.ToolbarFlowLayoutPanel.Size = new System.Drawing.Size(584, 29); | |||||
this.ToolbarFlowLayoutPanel.Size = new System.Drawing.Size(378, 29); | |||||
this.ToolbarFlowLayoutPanel.TabIndex = 2; | this.ToolbarFlowLayoutPanel.TabIndex = 2; | ||||
// | // | ||||
// LogForm | // LogForm | ||||
// | // | ||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); | ||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; | ||||
this.ClientSize = new System.Drawing.Size(590, 418); | |||||
this.ClientSize = new System.Drawing.Size(384, 140); | |||||
this.Controls.Add(this.tableLayoutPanel1); | this.Controls.Add(this.tableLayoutPanel1); | ||||
this.Menu = this.MainMenu; | this.Menu = this.MainMenu; | ||||
this.MinimumSize = new System.Drawing.Size(400, 200); | |||||
this.Name = "LogForm"; | this.Name = "LogForm"; | ||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | ||||
this.Text = "Log Viewer"; | this.Text = "Log Viewer"; | ||||
@@ -27,17 +27,21 @@ namespace Shadowsocks.View | |||||
this.controller = controller; | this.controller = controller; | ||||
this.filename = filename; | this.filename = filename; | ||||
InitializeComponent(); | InitializeComponent(); | ||||
this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); | |||||
Icon = Icon.FromHandle(Resources.ssw128.GetHicon()); | |||||
LogViewerConfig config = controller.GetConfigurationCopy().logViewer; | LogViewerConfig config = controller.GetConfigurationCopy().logViewer; | ||||
if (config == null) | if (config == null) | ||||
{ | |||||
config = new LogViewerConfig(); | config = new LogViewerConfig(); | ||||
topMostTrigger = config.topMost; | |||||
wrapTextTrigger = config.wrapText; | |||||
toolbarTrigger = config.toolbarShown; | |||||
LogMessageTextBox.BackColor = config.GetBackgroundColor(); | |||||
LogMessageTextBox.ForeColor = config.GetTextColor(); | |||||
LogMessageTextBox.Font = config.GetFont(); | |||||
} | |||||
else { | |||||
topMostTrigger = config.topMost; | |||||
wrapTextTrigger = config.wrapText; | |||||
toolbarTrigger = config.toolbarShown; | |||||
LogMessageTextBox.BackColor = config.GetBackgroundColor(); | |||||
LogMessageTextBox.ForeColor = config.GetTextColor(); | |||||
LogMessageTextBox.Font = config.GetFont(); | |||||
} | |||||
UpdateTexts(); | UpdateTexts(); | ||||
} | } | ||||
@@ -57,7 +61,7 @@ namespace Shadowsocks.View | |||||
WrapTextMenuItem.Text = I18N.GetString("&Wrap Text"); | WrapTextMenuItem.Text = I18N.GetString("&Wrap Text"); | ||||
TopMostMenuItem.Text = I18N.GetString("&Top Most"); | TopMostMenuItem.Text = I18N.GetString("&Top Most"); | ||||
ShowToolbarMenuItem.Text = I18N.GetString("&Show Toolbar"); | ShowToolbarMenuItem.Text = I18N.GetString("&Show Toolbar"); | ||||
this.Text = I18N.GetString("Log Viewer"); | |||||
Text = I18N.GetString("Log Viewer"); | |||||
} | } | ||||
private void Timer_Tick(object sender, EventArgs e) | private void Timer_Tick(object sender, EventArgs e) | ||||
@@ -118,8 +122,16 @@ namespace Shadowsocks.View | |||||
timer.Tick += Timer_Tick; | timer.Tick += Timer_Tick; | ||||
timer.Start(); | timer.Start(); | ||||
LogViewerConfig config = controller.GetConfigurationCopy().logViewer; | |||||
if (config == null) | |||||
config = new LogViewerConfig(); | |||||
Height = config.height; | |||||
Width = config.width; | |||||
Top = config.GetBestTop(); | |||||
Left = config.GetBestLeft(); | |||||
topMostTriggerLock = true; | topMostTriggerLock = true; | ||||
this.TopMost = TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger; | |||||
TopMost = TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger; | |||||
topMostTriggerLock = false; | topMostTriggerLock = false; | ||||
wrapTextTriggerLock = true; | wrapTextTriggerLock = true; | ||||
@@ -141,19 +153,23 @@ namespace Shadowsocks.View | |||||
config.SetFont(LogMessageTextBox.Font); | config.SetFont(LogMessageTextBox.Font); | ||||
config.SetBackgroundColor(LogMessageTextBox.BackColor); | config.SetBackgroundColor(LogMessageTextBox.BackColor); | ||||
config.SetTextColor(LogMessageTextBox.ForeColor); | config.SetTextColor(LogMessageTextBox.ForeColor); | ||||
config.top = Top; | |||||
config.left = Left; | |||||
config.height = Height; | |||||
config.width = Width; | |||||
controller.SaveLogViewerConfig(config); | controller.SaveLogViewerConfig(config); | ||||
} | } | ||||
private void OpenLocationMenuItem_Click(object sender, EventArgs e) | private void OpenLocationMenuItem_Click(object sender, EventArgs e) | ||||
{ | { | ||||
string argument = "/select, \"" + filename + "\""; | string argument = "/select, \"" + filename + "\""; | ||||
Console.WriteLine(argument); | |||||
Logging.Debug(argument); | |||||
System.Diagnostics.Process.Start("explorer.exe", argument); | System.Diagnostics.Process.Start("explorer.exe", argument); | ||||
} | } | ||||
private void ExitMenuItem_Click(object sender, EventArgs e) | private void ExitMenuItem_Click(object sender, EventArgs e) | ||||
{ | { | ||||
this.Close(); | |||||
Close(); | |||||
} | } | ||||
private void LogForm_Shown(object sender, EventArgs e) | private void LogForm_Shown(object sender, EventArgs e) | ||||
@@ -208,7 +224,7 @@ namespace Shadowsocks.View | |||||
} | } | ||||
#endregion | #endregion | ||||
#region Trigger the log messages wrapable, or not. | |||||
#region Trigger the log messages to wrapable, or not. | |||||
bool wrapTextTrigger = false; | bool wrapTextTrigger = false; | ||||
bool wrapTextTriggerLock = false; | bool wrapTextTriggerLock = false; | ||||
@@ -241,7 +257,7 @@ namespace Shadowsocks.View | |||||
} | } | ||||
#endregion | #endregion | ||||
#region Trigger this window top most, or not. | |||||
#region Trigger the window to top most, or not. | |||||
bool topMostTrigger = false; | bool topMostTrigger = false; | ||||
bool topMostTriggerLock = false; | bool topMostTriggerLock = false; | ||||
@@ -250,7 +266,7 @@ namespace Shadowsocks.View | |||||
topMostTriggerLock = true; | topMostTriggerLock = true; | ||||
topMostTrigger = !topMostTrigger; | topMostTrigger = !topMostTrigger; | ||||
this.TopMost = topMostTrigger; | |||||
TopMost = topMostTrigger; | |||||
TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger; | TopMostMenuItem.Checked = TopMostCheckBox.Checked = topMostTrigger; | ||||
topMostTriggerLock = false; | topMostTriggerLock = false; | ||||
@@ -44,6 +44,8 @@ namespace Shadowsocks.View | |||||
private MenuItem editOnlinePACItem; | private MenuItem editOnlinePACItem; | ||||
private MenuItem autoCheckUpdatesToggleItem; | private MenuItem autoCheckUpdatesToggleItem; | ||||
private ConfigForm configForm; | private ConfigForm configForm; | ||||
private List<LogForm> logForms = new List<LogForm>(); | |||||
private bool logFormsVisible = false; | |||||
private string _urlToOpen; | private string _urlToOpen; | ||||
public MenuViewController(ShadowsocksController controller) | public MenuViewController(ShadowsocksController controller) | ||||
@@ -289,7 +291,6 @@ namespace Shadowsocks.View | |||||
} | } | ||||
} | } | ||||
private void LoadCurrentConfiguration() | private void LoadCurrentConfiguration() | ||||
{ | { | ||||
Configuration config = controller.GetConfigurationCopy(); | Configuration config = controller.GetConfigurationCopy(); | ||||
@@ -357,6 +358,32 @@ namespace Shadowsocks.View | |||||
} | } | ||||
} | } | ||||
private void ShowLogForms() | |||||
{ | |||||
if (logForms.Count == 0) | |||||
{ | |||||
LogForm f = new LogForm(controller, Logging.LogFile); | |||||
f.Show(); | |||||
f.FormClosed += logForm_FormClosed; | |||||
logForms.Add(f); | |||||
logFormsVisible = true; | |||||
} | |||||
else | |||||
{ | |||||
logFormsVisible = !logFormsVisible; | |||||
foreach (LogForm f in logForms) | |||||
{ | |||||
f.Visible = logFormsVisible; | |||||
} | |||||
} | |||||
} | |||||
void logForm_FormClosed(object sender, FormClosedEventArgs e) | |||||
{ | |||||
logForms.Remove((LogForm)sender); | |||||
} | |||||
void configForm_FormClosed(object sender, FormClosedEventArgs e) | void configForm_FormClosed(object sender, FormClosedEventArgs e) | ||||
{ | { | ||||
configForm = null; | configForm = null; | ||||
@@ -451,11 +478,13 @@ namespace Shadowsocks.View | |||||
private void ShowLogItem_Click(object sender, EventArgs e) | private void ShowLogItem_Click(object sender, EventArgs e) | ||||
{ | { | ||||
string argument = Logging.LogFile; | |||||
LogForm f = new LogForm(controller, Logging.LogFile); | |||||
f.Show(); | |||||
f.FormClosed += logForm_FormClosed; | |||||
new LogForm(controller, argument).Show(); | |||||
logForms.Add(f); | |||||
} | } | ||||
private void StatisticsConfigItem_Click(object sender, EventArgs e) | private void StatisticsConfigItem_Click(object sender, EventArgs e) | ||||
{ | { | ||||
StatisticsStrategyConfigurationForm form = new StatisticsStrategyConfigurationForm(controller); | StatisticsStrategyConfigurationForm form = new StatisticsStrategyConfigurationForm(controller); | ||||
@@ -564,9 +593,11 @@ namespace Shadowsocks.View | |||||
Process.Start(_urlToOpen); | Process.Start(_urlToOpen); | ||||
} | } | ||||
private void AutoStartupItem_Click(object sender, EventArgs e) { | |||||
private void AutoStartupItem_Click(object sender, EventArgs e) | |||||
{ | |||||
AutoStartupItem.Checked = !AutoStartupItem.Checked; | AutoStartupItem.Checked = !AutoStartupItem.Checked; | ||||
if (!AutoStartup.Set(AutoStartupItem.Checked)) { | |||||
if (!AutoStartup.Set(AutoStartupItem.Checked)) | |||||
{ | |||||
MessageBox.Show(I18N.GetString("Failed to update registry")); | MessageBox.Show(I18N.GetString("Failed to update registry")); | ||||
} | } | ||||
} | } | ||||
@@ -1,5 +1,8 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<packages> | |||||
<package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" /> | |||||
<package id="System.Net.Http" version="2.0.20710.0" targetFramework="net45" /> | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<packages> | |||||
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" /> | |||||
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" /> | |||||
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" /> | |||||
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" /> | |||||
<package id="System.Net.Http" version="4.0.0" targetFramework="net45" /> | |||||
</packages> | </packages> |
@@ -17,6 +17,8 @@ | |||||
<IsCodedUITest>False</IsCodedUITest> | <IsCodedUITest>False</IsCodedUITest> | ||||
<TestProjectType>UnitTest</TestProjectType> | <TestProjectType>UnitTest</TestProjectType> | ||||
<TargetFrameworkProfile /> | <TargetFrameworkProfile /> | ||||
<NuGetPackageImportStamp> | |||||
</NuGetPackageImportStamp> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> | ||||
<OutputPath>bin\x86\Debug\</OutputPath> | <OutputPath>bin\x86\Debug\</OutputPath> | ||||
@@ -30,8 +32,29 @@ | |||||
<StartupObject /> | <StartupObject /> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="System" /> | <Reference Include="System" /> | ||||
<Reference Include="System.Net" /> | |||||
<Reference Include="System.Net.Http" /> | <Reference Include="System.Net.Http" /> | ||||
<Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>..\shadowsocks-csharp\3rd\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath> | |||||
<Private>True</Private> | |||||
</Reference> | |||||
<Reference Include="System.Net.Http.WebRequest" /> | <Reference Include="System.Net.Http.WebRequest" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<Choose> | <Choose> | ||||
@@ -79,6 +102,13 @@ | |||||
</Choose> | </Choose> | ||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> | <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> | ||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||
<Import Project="..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" /> | |||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | |||||
<PropertyGroup> | |||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> | |||||
</PropertyGroup> | |||||
<Error Condition="!Exists('..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\shadowsocks-csharp\3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" /> | |||||
</Target> | |||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | ||||
Other similar extension points exist, see Microsoft.Common.targets. | Other similar extension points exist, see Microsoft.Common.targets. | ||||
<Target Name="BeforeBuild"> | <Target Name="BeforeBuild"> | ||||