diff --git a/appveyor.yml b/appveyor.yml
index 4616e5956..803437c49 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -30,7 +30,7 @@
 #---------------------------------#
 
 # Build worker image (VM template)
-image: Visual Studio 2017
+image: Visual Studio 2019
 
 # scripts that are called at very beginning, before repo cloning
 # init:
diff --git a/shadowsocks-csharp/Controller/HotkeyReg.cs b/shadowsocks-csharp/Controller/HotkeyReg.cs
index 90a3dee9c..2ebef2120 100644
--- a/shadowsocks-csharp/Controller/HotkeyReg.cs
+++ b/shadowsocks-csharp/Controller/HotkeyReg.cs
@@ -50,7 +50,7 @@ public static bool RegHotkeyFromString(string hotkeyStr, string callbackName, Ac
 
             var callback = _callback as HotKeys.HotKeyCallBackHandler;
 
-            if (hotkeyStr.IsNullOrEmpty())
+            if (string.IsNullOrEmpty(hotkeyStr))
             {
                 HotKeys.UnregExistingHotkey(callback);
                 onComplete?.Invoke(RegResult.UnregSuccess);
diff --git a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
index f6d9a3d6d..112c54934 100644
--- a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
+++ b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs
@@ -214,7 +214,7 @@ private void UpdateRecords()
                         AppendRecord(id, record);
                     }
                 }
-                catch (Exception e)
+                catch
                 {
                     logger.Debug("config changed asynchrously, just ignore this server");
                 }
diff --git a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
index e4489f60c..be6048441 100644
--- a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
+++ b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs
@@ -219,16 +219,14 @@ private static string MergePACFile(IList<DomainObject> domains, bool blacklist)
             return abpContent;
         }
 
-        private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' };
-
         private static List<string> PreProcessGFWList(string content)
         {
             List<string> valid_lines = new List<string>();
-            using (var sr = new StringReader(content))
+            using (var stringReader = new StringReader(content))
             {
-                foreach (var line in sr.NonWhiteSpaceLines())
+                for (string line = stringReader.ReadLine(); line != null; line = stringReader.ReadLine())
                 {
-                    if (line.BeginWithAny(IgnoredLineBegins))
+                    if (string.IsNullOrWhiteSpace(line) || line.StartsWith("!") || line.StartsWith("["))
                         continue;
                     valid_lines.Add(line);
                 }
diff --git a/shadowsocks-csharp/Controller/Service/Sip003Plugin.cs b/shadowsocks-csharp/Controller/Service/Sip003Plugin.cs
index a0048e149..7024c648e 100644
--- a/shadowsocks-csharp/Controller/Service/Sip003Plugin.cs
+++ b/shadowsocks-csharp/Controller/Service/Sip003Plugin.cs
@@ -122,12 +122,13 @@ public bool StartIfNeeded()
 
         public string ExpandEnvironmentVariables(string name, StringDictionary environmentVariables = null)
         {
+            name = name.ToLower();
             // Expand the environment variables from the new process itself
             if (environmentVariables != null)
             {
                 foreach(string key in environmentVariables.Keys)
                 {
-                    name = name.Replace($"%{key}%", environmentVariables[key], StringComparison.OrdinalIgnoreCase);
+                    name = name.Replace($"%{key.ToLower()}%", environmentVariables[key]);
                 }
             }
             // Also expand the environment variables from current main process (system)
diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs
index 590485e0b..cb915ff76 100644
--- a/shadowsocks-csharp/Controller/ShadowsocksController.cs
+++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs
@@ -420,7 +420,7 @@ public bool AddServerBySSURL(string ssURL)
         {
             try
             {
-                if (ssURL.IsNullOrEmpty() || ssURL.IsWhiteSpace())
+                if (string.IsNullOrWhiteSpace(ssURL))
                     return false;
 
                 var servers = Server.GetServers(ssURL);
diff --git a/shadowsocks-csharp/Controller/System/Hotkeys/HotkeyCallbacks.cs b/shadowsocks-csharp/Controller/System/Hotkeys/HotkeyCallbacks.cs
index cb60d7395..7c94c93cc 100644
--- a/shadowsocks-csharp/Controller/System/Hotkeys/HotkeyCallbacks.cs
+++ b/shadowsocks-csharp/Controller/System/Hotkeys/HotkeyCallbacks.cs
@@ -23,7 +23,7 @@ public static void InitInstance(ShadowsocksController controller)
         /// <returns></returns>
         public static Delegate GetCallback(string methodname)
         {
-            if (methodname.IsNullOrEmpty()) throw new ArgumentException(nameof(methodname));
+            if (string.IsNullOrEmpty(methodname)) throw new ArgumentException(nameof(methodname));
             MethodInfo dynMethod = typeof(HotkeyCallbacks).GetMethod(methodname,
                 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase);
             return dynMethod == null ? null : Delegate.CreateDelegate(typeof(HotKeys.HotKeyCallBackHandler), Instance, dynMethod);
diff --git a/shadowsocks-csharp/Controller/System/Hotkeys/Hotkeys.cs b/shadowsocks-csharp/Controller/System/Hotkeys/Hotkeys.cs
index 450693213..a55591ef4 100644
--- a/shadowsocks-csharp/Controller/System/Hotkeys/Hotkeys.cs
+++ b/shadowsocks-csharp/Controller/System/Hotkeys/Hotkeys.cs
@@ -110,7 +110,7 @@ public static HotKey Str2HotKey(string s)
         {
             try
             {
-                if (s.IsNullOrEmpty()) return null;
+                if (string.IsNullOrEmpty(s)) return null;
                 int offset = s.LastIndexOf("+", StringComparison.OrdinalIgnoreCase);
                 if (offset <= 0) return null;
                 string modifierStr = s.Substring(0, offset).Trim();
diff --git a/shadowsocks-csharp/Controller/System/SystemProxy.cs b/shadowsocks-csharp/Controller/System/SystemProxy.cs
index 1d61dd86f..ee767e128 100644
--- a/shadowsocks-csharp/Controller/System/SystemProxy.cs
+++ b/shadowsocks-csharp/Controller/System/SystemProxy.cs
@@ -36,7 +36,7 @@ public static void Update(Configuration config, bool forceDisable, PACServer pac
                     else
                     {
                         string pacUrl;
-                        if (config.useOnlinePac && !config.pacUrl.IsNullOrEmpty())
+                        if (config.useOnlinePac && !string.IsNullOrEmpty(config.pacUrl))
                         {
                             pacUrl = config.pacUrl;
                         }
diff --git a/shadowsocks-csharp/Encryption/EncryptorFactory.cs b/shadowsocks-csharp/Encryption/EncryptorFactory.cs
index fcae221ab..7e1d6264c 100644
--- a/shadowsocks-csharp/Encryption/EncryptorFactory.cs
+++ b/shadowsocks-csharp/Encryption/EncryptorFactory.cs
@@ -68,7 +68,7 @@ static EncryptorFactory()
 
         public static IEncryptor GetEncryptor(string method, string password)
         {
-            if (method.IsNullOrEmpty())
+            if (string.IsNullOrEmpty(method))
             {
                 method = Model.Server.DefaultMethod;
             }
diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs
index a11cc46ba..cd16032b6 100644
--- a/shadowsocks-csharp/Model/Configuration.cs
+++ b/shadowsocks-csharp/Model/Configuration.cs
@@ -292,13 +292,13 @@ public static void CheckLocalPort(int port)
 
         private static void CheckPassword(string password)
         {
-            if (password.IsNullOrEmpty())
+            if (string.IsNullOrEmpty(password))
                 throw new ArgumentException(I18N.GetString("Password can not be blank"));
         }
 
         public static void CheckServer(string server)
         {
-            if (server.IsNullOrEmpty())
+            if (string.IsNullOrEmpty(server))
                 throw new ArgumentException(I18N.GetString("Server IP can not be blank"));
         }
 
@@ -311,13 +311,13 @@ public static void CheckTimeout(int timeout, int maxTimeout)
 
         public static void CheckProxyAuthUser(string user)
         {
-            if (user.IsNullOrEmpty())
+            if (string.IsNullOrEmpty(user))
                 throw new ArgumentException(I18N.GetString("Auth user can not be blank"));
         }
 
         public static void CheckProxyAuthPwd(string pwd)
         {
-            if (pwd.IsNullOrEmpty())
+            if (string.IsNullOrEmpty(pwd))
                 throw new ArgumentException(I18N.GetString("Auth pwd can not be blank"));
         }
     }
diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs
index fe0e3c040..836d9d8db 100755
--- a/shadowsocks-csharp/Model/Server.cs
+++ b/shadowsocks-csharp/Model/Server.cs
@@ -62,13 +62,13 @@ public override int GetHashCode()
 
         public override string ToString()
         {
-            if (server.IsNullOrEmpty())
+            if (string.IsNullOrEmpty(server))
             {
                 return I18N.GetString("New server");
             }
 
             string serverStr = $"{FormalHostName}:{server_port}";
-            return remarks.IsNullOrEmpty()
+            return string.IsNullOrEmpty(remarks)
                 ? serverStr
                 : $"{remarks} ({serverStr})";
         }
@@ -99,7 +99,7 @@ public string GetURL(bool legacyUrl = false)
                     server_port
                     );
 
-                if (!plugin.IsNullOrWhiteSpace())
+                if (!string.IsNullOrWhiteSpace(plugin))
                 {
 
                     string pluginPart = plugin;
@@ -112,7 +112,7 @@ public string GetURL(bool legacyUrl = false)
                 }
             }
 
-            if (!remarks.IsNullOrEmpty())
+            if (!string.IsNullOrEmpty(remarks))
             {
                 tag = $"#{HttpUtility.UrlEncode(remarks, Encoding.UTF8)}";
             }
@@ -157,7 +157,7 @@ private static Server ParseLegacyURL(string ssURL)
             Server server = new Server();
             var base64 = match.Groups["base64"].Value.TrimEnd('/');
             var tag = match.Groups["tag"].Value;
-            if (!tag.IsNullOrEmpty())
+            if (!string.IsNullOrEmpty(tag))
             {
                 server.remarks = HttpUtility.UrlDecode(tag, Encoding.UTF8);
             }
@@ -183,7 +183,7 @@ private static Server ParseLegacyURL(string ssURL)
         public static Server ParseURL(string serverUrl)
         {
             string _serverUrl = serverUrl.Trim();
-            if (!_serverUrl.BeginWith("ss://", StringComparison.InvariantCultureIgnoreCase))
+            if (!_serverUrl.StartsWith("ss://", StringComparison.InvariantCultureIgnoreCase))
             {
                 return null;
             }
diff --git a/shadowsocks-csharp/Proxy/HttpProxy.cs b/shadowsocks-csharp/Proxy/HttpProxy.cs
index dd13b779d..b7580f04b 100644
--- a/shadowsocks-csharp/Proxy/HttpProxy.cs
+++ b/shadowsocks-csharp/Proxy/HttpProxy.cs
@@ -39,8 +39,6 @@ private class HttpState
 
             public object AsyncState { get; set; }
 
-            public int BytesToRead;
-
             public Exception ex { get; set; }
         }
 
@@ -199,7 +197,7 @@ private bool OnLineRead(string line, object state)
             }
             else
             {
-                if (line.IsNullOrEmpty())
+                if (string.IsNullOrEmpty(line))
                 {
                     return true;
                 }
diff --git a/shadowsocks-csharp/StringEx.cs b/shadowsocks-csharp/StringEx.cs
deleted file mode 100644
index 96880e190..000000000
--- a/shadowsocks-csharp/StringEx.cs
+++ /dev/null
@@ -1,314 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-
-#if EXPOSE_EVERYTHING || EXPOSE_STRINGEX
-public
-#endif
-static partial class StringEx
-{
-#pragma warning disable 1591
-
-    public static StringComparison GlobalDefaultComparison { get; set; } = StringComparison.Ordinal;
-
-    [ThreadStatic]
-    private static StringComparison? _DefaultComparison;
-    public static StringComparison DefaultComparison
-    {
-        get { return _DefaultComparison ?? GlobalDefaultComparison; }
-        set { _DefaultComparison = value; }
-    }
-
-    #region basic String methods
-
-    public static bool IsNullOrEmpty(this string value)
-        => string.IsNullOrEmpty(value);
-
-    public static bool IsNullOrWhiteSpace(this string value)
-        => string.IsNullOrWhiteSpace(value);
-
-    public static bool IsWhiteSpace(this string value)
-    {
-        foreach (var c in value)
-        {
-            if (char.IsWhiteSpace(c)) continue;
-
-            return false;
-        }
-        return true;
-    }
-
-#if !PCL
-    public static string IsInterned(this string value)
-    {
-        if (value == null)
-            throw new ArgumentNullException(nameof(value));
-
-        return string.IsInterned(value);
-    }
-
-    public static string Intern(this string value)
-    {
-        if (value == null)
-            throw new ArgumentNullException(nameof(value));
-
-        return string.Intern(value);
-    }
-#endif
-
-#if UNSAFE
-    public static unsafe string ToLowerForASCII(this string value)
-    {
-        if (value.IsNullOrWhiteSpace())
-            return value;
-
-        value = string.Copy(value);
-        fixed (char* low = value)
-        {
-            var end = low + value.Length;
-            for (var p = low; p < end; p++)
-            {
-                var c = *p;
-                if (c < 'A' || c > 'Z')
-                    continue;
-                *p = (char)(c + 0x20);
-            }
-        }
-        return value;
-    }
-
-    public static unsafe string ToUpperForASCII(this string value)
-    {
-        if (value.IsNullOrWhiteSpace())
-            return value;
-
-        value = string.Copy(value);
-        fixed (char* low = value)
-        {
-            var end = low + value.Length;
-            for (var p = low; p < end; p++)
-            {
-                var c = *p;
-                if (c < 'a' || c > 'z')
-                    continue;
-                *p = (char)(c - 0x20);
-            }
-        }
-        return value;
-    }
-#else
-    public static string ToLowerForASCII(this string value)
-    {
-        if (value.IsNullOrWhiteSpace())
-            return value;
-
-        var sb = new StringBuilder(value.Length);
-        foreach (var c in value)
-        {
-            if (c < 'A' || c > 'Z')
-                sb.Append(c);
-            else
-                sb.Append((char)(c + 0x20));
-        }
-        return sb.ToString();
-    }
-
-    public static string ToUpperForASCII(this string value)
-    {
-        if (value.IsNullOrWhiteSpace())
-            return value;
-
-        var sb = new StringBuilder(value.Length);
-        foreach (var c in value)
-        {
-            if (c < 'a' || c > 'z')
-                sb.Append(c);
-            else
-                sb.Append((char)(c - 0x20));
-        }
-        return sb.ToString();
-    }
-#endif
-
-    #endregion
-
-    #region comparing
-
-    #region Is
-
-    public static bool Is(this string a, string b)
-        => string.Equals(a, b, DefaultComparison);
-    public static bool Is(this string a, string b, StringComparison comparisonType)
-        => string.Equals(a, b, comparisonType);
-
-    #endregion
-
-    #region BeginWith
-
-    public static bool BeginWith(this string s, char c)
-    {
-        if (s.IsNullOrEmpty()) return false;
-        return s[0] == c;
-    }
-    public static bool BeginWithAny(this string s, IEnumerable<char> chars)
-    {
-        if (s.IsNullOrEmpty()) return false;
-        return chars.Contains(s[0]);
-    }
-    public static bool BeginWithAny(this string s, params char[] chars)
-        => s.BeginWithAny(chars.AsEnumerable());
-
-    public static bool BeginWith(this string a, string b)
-    {
-        if (a == null || b == null) return false;
-
-        return a.StartsWith(b, DefaultComparison);
-    }
-    public static bool BeginWith(this string a, string b, StringComparison comparisonType)
-    {
-        if (a == null || b == null) return false;
-
-        return a.StartsWith(b, comparisonType);
-    }
-#if !PCL
-    public static bool BeginWith(this string a, string b, bool ignoreCase, CultureInfo culture)
-    {
-        if (a == null || b == null) return false;
-
-        return a.StartsWith(b, ignoreCase, culture);
-    }
-#endif
-
-    #endregion
-
-    #region FinishWith
-
-    public static bool FinishWith(this string s, char c)
-    {
-        if (s.IsNullOrEmpty()) return false;
-        return s.Last() == c;
-    }
-    public static bool FinishWithAny(this string s, IEnumerable<char> chars)
-    {
-        if (s.IsNullOrEmpty()) return false;
-        return chars.Contains(s.Last());
-    }
-    public static bool FinishWithAny(this string s, params char[] chars)
-        => s.FinishWithAny(chars.AsEnumerable());
-
-    public static bool FinishWith(this string a, string b)
-    {
-        if (a == null || b == null) return false;
-
-        return a.EndsWith(b, DefaultComparison);
-    }
-    public static bool FinishWith(this string a, string b, StringComparison comparisonType)
-    {
-        if (a == null || b == null) return false;
-
-        return a.EndsWith(b, comparisonType);
-    }
-#if !PCL
-    public static bool FinishWith(this string a, string b, bool ignoreCase, CultureInfo culture)
-    {
-        if (a == null || b == null) return false;
-
-        return a.EndsWith(b, ignoreCase, culture);
-    }
-#endif
-
-    #endregion
-
-    #endregion
-
-    #region ToLines
-
-    public static IEnumerable<string> ToLines(this TextReader reader)
-    {
-        string line;
-        while ((line = reader.ReadLine()) != null)
-            yield return line;
-    }
-    public static IEnumerable<string> NonEmptyLines(this TextReader reader)
-    {
-        string line;
-        while ((line = reader.ReadLine()) != null)
-        {
-            if (line == "") continue;
-            yield return line;
-        }
-    }
-    public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
-    {
-        string line;
-        while ((line = reader.ReadLine()) != null)
-        {
-            if (line.IsWhiteSpace()) continue;
-            yield return line;
-        }
-    }
-
-    #endregion
-
-    #region others
-
-    private static readonly char[][] Quotes = new[]
-    {
-        "\"\"",
-        "''",
-        "“”",
-        "‘’",
-        "『』",
-        "「」",
-        "〖〗",
-        "【】",
-    }.Select(s => s.ToCharArray()).ToArray();
-    public static string Enquote(this string value)
-    {
-        if (value == null)
-            return "(null)";
-
-        foreach (var pair in Quotes)
-        {
-            if (value.IndexOfAny(pair) < 0)
-                return pair[0] + value + pair[1];
-        }
-
-        return '"' + value.Replace("\\", @"\\").Replace("\"", @"\""") + '"';
-    }
-
-    public static string Replace(this string value, string find, string rep, StringComparison comparsionType)
-    {
-        if (find.IsNullOrEmpty())
-            throw new ArgumentException(null, nameof(find));
-        if (rep == null)
-            rep = "";
-        if (value.IsNullOrEmpty())
-            return value;
-
-        var sb = new StringBuilder(value.Length);
-
-        var last = 0;
-        var len = find.Length;
-        var idx = value.IndexOf(find, DefaultComparison);
-        while (idx != -1)
-        {
-            sb.Append(value.Substring(last, idx - last));
-            sb.Append(rep);
-            idx += len;
-
-            last = idx;
-            idx = value.IndexOf(find, idx, comparsionType);
-        }
-        sb.Append(value.Substring(last));
-
-        return sb.ToString();
-    }
-    public static string ReplaceEx(this string value, string find, string rep)
-        => value.Replace(find, rep, DefaultComparison);
-
-    #endregion
-}
diff --git a/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs b/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs
index b1ffcac44..220576f6b 100644
--- a/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs
+++ b/shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs
@@ -212,7 +212,7 @@ private static void ExecSysproxy(string arguments)
 
                     if (arguments == "query")
                     {
-                        if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty())
+                        if (string.IsNullOrWhiteSpace(stdout))
                         {
                             // we cannot get user settings
                             throw new ProxyException(ProxyExceptionType.QueryReturnEmpty);
diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs
index cbfed99b8..a24ce2c2d 100755
--- a/shadowsocks-csharp/Util/Util.cs
+++ b/shadowsocks-csharp/Util/Util.cs
@@ -238,7 +238,7 @@ public static RegistryKey OpenRegKey(string name, bool writable, RegistryHive hi
             // we are building x86 binary for both x86 and x64, which will
             // cause problem when opening registry key
             // detect operating system instead of CPU
-            if (name.IsNullOrEmpty()) throw new ArgumentException(nameof(name));
+            if (string.IsNullOrEmpty(name)) throw new ArgumentException(nameof(name));
             try
             {
                 RegistryKey userKey = RegistryKey.OpenBaseKey(hive,
diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs
index dad4c5351..ab029f7e2 100755
--- a/shadowsocks-csharp/View/ConfigForm.cs
+++ b/shadowsocks-csharp/View/ConfigForm.cs
@@ -310,7 +310,7 @@ private bool GetServerDetailsFromUI(out Server server, bool isSave = false, bool
         {
             password = null;
             string outPassword;
-            if ((outPassword = PasswordTextBox.Text).IsNullOrWhiteSpace())
+            if (string.IsNullOrWhiteSpace(outPassword = PasswordTextBox.Text))
             {
                 if (!isSave && !isCopy && ServersListBox.Items.Count > 1 && I18N.GetString("New server").Equals(ServersListBox.Items[_lastSelectedIndex].ToString()))
                 {
diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs
index a2f971a35..8bcd6d9cc 100644
--- a/shadowsocks-csharp/View/MenuViewController.cs
+++ b/shadowsocks-csharp/View/MenuViewController.cs
@@ -868,11 +868,11 @@ private void OnlinePACItem_Click(object sender, EventArgs e)
         {
             if (!onlinePACItem.Checked)
             {
-                if (controller.GetConfigurationCopy().pacUrl.IsNullOrEmpty())
+                if (string.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl))
                 {
                     UpdateOnlinePACURLItem_Click(sender, e);
                 }
-                if (!controller.GetConfigurationCopy().pacUrl.IsNullOrEmpty())
+                if (!string.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl))
                 {
                     localPACItem.Checked = false;
                     onlinePACItem.Checked = true;
@@ -889,7 +889,7 @@ private void UpdateOnlinePACURLItem_Click(object sender, EventArgs e)
                 I18N.GetString("Please input PAC Url"),
                 I18N.GetString("Edit Online PAC URL"),
                 origPacUrl, -1, -1);
-            if (!pacUrl.IsNullOrEmpty() && pacUrl != origPacUrl)
+            if (!string.IsNullOrEmpty(pacUrl) && pacUrl != origPacUrl)
             {
                 controller.SavePACUrl(pacUrl);
             }
diff --git a/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs b/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs
index d9787dde4..89b4f12a2 100644
--- a/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs
+++ b/shadowsocks-csharp/View/OnlineConfigForm.Designer.cs
@@ -213,6 +213,6 @@ private void InitializeComponent()
         private System.Windows.Forms.Button DeleteButton;
         private System.Windows.Forms.Button OkButton;
         private System.Windows.Forms.Button UpdateAllButton;
-        private System.Windows.Forms.Button CancelButton;
+        private new System.Windows.Forms.Button CancelButton;
     }
 }
\ No newline at end of file
diff --git a/shadowsocks-csharp/app.config b/shadowsocks-csharp/app.config
index f1118d57b..af2e1137a 100755
--- a/shadowsocks-csharp/app.config
+++ b/shadowsocks-csharp/app.config
@@ -1,22 +1,30 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <configuration>
 <configSections>
     <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-        <section name="Shadowsocks.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
+        <section name="Shadowsocks.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
     </sectionGroup>
 </configSections>
 <startup>
-  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
+  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
 </startup>
   <runtime>
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
       <dependentAssembly>
-        <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
-        <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0"/>
+        <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
       </dependentAssembly>
       <dependentAssembly>
-        <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
-        <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0"/>
+        <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
       </dependentAssembly>
     </assemblyBinding>
   </runtime>
diff --git a/shadowsocks-csharp/packages.config b/shadowsocks-csharp/packages.config
index a888c1a99..cbfeadba0 100644
--- a/shadowsocks-csharp/packages.config
+++ b/shadowsocks-csharp/packages.config
@@ -1,31 +1,30 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Caseless.Fody" version="1.8.3" targetFramework="net472" />
+  <package id="Caseless.Fody" version="1.9.0" targetFramework="net472" />
   <package id="CommandLineParser" version="2.8.0" targetFramework="net472" />
-  <package id="Costura.Fody" version="3.3.3" targetFramework="net472" />
-  <package id="DynamicData" version="6.16.6" targetFramework="net472" />
-  <package id="Fody" version="4.2.1" targetFramework="net472" developmentDependency="true" />
+  <package id="Costura.Fody" version="4.1.0" targetFramework="net472" />
+  <package id="DynamicData" version="6.17.14" targetFramework="net472" />
+  <package id="Fody" version="6.2.6" targetFramework="net472" developmentDependency="true" />
   <package id="GlobalHotKey" version="1.1.0" targetFramework="net472" />
-  <package id="Google.Protobuf" version="3.11.4" targetFramework="net472" />
-  <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
-  <package id="NLog" version="4.6.8" targetFramework="net472" />
+  <package id="Google.Protobuf" version="3.13.0" targetFramework="net472" />
+  <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
+  <package id="NLog" version="4.7.5" targetFramework="net472" />
   <package id="ReactiveUI" version="11.5.35" targetFramework="net472" />
   <package id="ReactiveUI.WPF" version="11.5.35" targetFramework="net472" />
-  <package id="Splat" version="9.5.20" targetFramework="net472" />
-  <package id="StringEx.CS" version="0.3.1" targetFramework="net472" developmentDependency="true" />
-  <package id="System.Buffers" version="4.4.0" targetFramework="net472" />
+  <package id="Splat" version="9.5.49" targetFramework="net472" />
+  <package id="System.Buffers" version="4.5.1" targetFramework="net472" />
   <package id="System.IO" version="4.3.0" targetFramework="net472" />
-  <package id="System.Memory" version="4.5.2" targetFramework="net472" />
+  <package id="System.Memory" version="4.5.4" targetFramework="net472" />
   <package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
-  <package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
+  <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
   <package id="System.Reactive" version="4.4.1" targetFramework="net472" />
-  <package id="System.Runtime" version="4.3.0" targetFramework="net472" />
-  <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net472" />
-  <package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net472" />
+  <package id="System.Runtime" version="4.3.1" targetFramework="net472" />
+  <package id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" targetFramework="net472" />
+  <package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net472" />
   <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
   <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
-  <package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net472" />
+  <package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" />
   <package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
   <package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
-  <package id="ZXing.Net" version="0.16.5" targetFramework="net472" />
+  <package id="ZXing.Net" version="0.16.6" targetFramework="net472" />
 </packages>
\ No newline at end of file
diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj
index dc63c3644..6620a009e 100644
--- a/shadowsocks-csharp/shadowsocks-csharp.csproj
+++ b/shadowsocks-csharp/shadowsocks-csharp.csproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="..\packages\Costura.Fody.3.3.3\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.3.3.3\build\Costura.Fody.props')" />
-  <Import Project="..\packages\Caseless.Fody.1.8.3\build\Caseless.Fody.props" Condition="Exists('..\packages\Caseless.Fody.1.8.3\build\Caseless.Fody.props')" />
+  <Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
+  <Import Project="..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props" Condition="Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -69,31 +69,31 @@
     <ApplicationManifest>app.manifest</ApplicationManifest>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="Caseless, Version=1.8.3.0, Culture=neutral, PublicKeyToken=409b3227471b0f0d, processorArchitecture=MSIL">
-      <HintPath>..\packages\Caseless.Fody.1.8.3\lib\net452\Caseless.dll</HintPath>
+    <Reference Include="Caseless, Version=1.9.0.0, Culture=neutral, PublicKeyToken=409b3227471b0f0d, processorArchitecture=MSIL">
+      <HintPath>..\packages\Caseless.Fody.1.9.0\lib\net452\Caseless.dll</HintPath>
     </Reference>
     <Reference Include="CommandLine, Version=2.8.0.0, Culture=neutral, PublicKeyToken=5a870481e358d379, processorArchitecture=MSIL">
       <HintPath>..\packages\CommandLineParser.2.8.0\lib\net461\CommandLine.dll</HintPath>
     </Reference>
-    <Reference Include="Costura, Version=3.3.3.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
-      <HintPath>..\packages\Costura.Fody.3.3.3\lib\net40\Costura.dll</HintPath>
+    <Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
+      <HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath>
     </Reference>
-    <Reference Include="DynamicData, Version=6.16.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\DynamicData.6.16.6\lib\net461\DynamicData.dll</HintPath>
+    <Reference Include="DynamicData, Version=6.17.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\DynamicData.6.17.14\lib\net461\DynamicData.dll</HintPath>
     </Reference>
     <Reference Include="GlobalHotKey, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\GlobalHotKey.1.1.0\lib\GlobalHotKey.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Protobuf, Version=3.11.4.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
-      <HintPath>..\packages\Google.Protobuf.3.11.4\lib\net45\Google.Protobuf.dll</HintPath>
+    <Reference Include="Google.Protobuf, Version=3.13.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+      <HintPath>..\packages\Google.Protobuf.3.13.0\lib\net45\Google.Protobuf.dll</HintPath>
     </Reference>
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="Microsoft.VisualBasic" />
     <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
-      <HintPath>..\packages\NLog.4.6.8\lib\net45\NLog.dll</HintPath>
+      <HintPath>..\packages\NLog.4.7.5\lib\net45\NLog.dll</HintPath>
     </Reference>
     <Reference Include="PresentationCore" />
     <Reference Include="PresentationFramework" />
@@ -104,11 +104,11 @@
       <HintPath>..\packages\ReactiveUI.WPF.11.5.35\lib\net472\ReactiveUI.WPF.dll</HintPath>
     </Reference>
     <Reference Include="Splat, Version=9.5.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Splat.9.5.20\lib\net461\Splat.dll</HintPath>
+      <HintPath>..\packages\Splat.9.5.49\lib\net461\Splat.dll</HintPath>
     </Reference>
     <Reference Include="System" />
-    <Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
+    <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
     </Reference>
     <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Configuration" />
@@ -122,8 +122,8 @@
     </Reference>
     <Reference Include="System.IO.Compression" />
     <Reference Include="System.Management" />
-    <Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath>
+    <Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
     </Reference>
     <Reference Include="System.Net" />
     <Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
@@ -132,23 +132,23 @@
       <Private>True</Private>
     </Reference>
     <Reference Include="System.Numerics" />
-    <Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
+    <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
     </Reference>
     <Reference Include="System.Reactive, Version=4.4.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
       <HintPath>..\packages\System.Reactive.4.4.1\lib\net46\System.Reactive.dll</HintPath>
     </Reference>
-    <Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath>
+    <Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath>
       <Private>True</Private>
       <Private>True</Private>
     </Reference>
-    <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
+    <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
     </Reference>
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
+      <HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
       <Private>True</Private>
       <Private>True</Private>
     </Reference>
@@ -162,8 +162,8 @@
       <Private>True</Private>
       <Private>True</Private>
     </Reference>
-    <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
+    <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
       <Private>True</Private>
       <Private>True</Private>
     </Reference>
@@ -184,11 +184,11 @@
     <Reference Include="UIAutomationProvider" />
     <Reference Include="WindowsBase" />
     <Reference Include="WindowsFormsIntegration" />
-    <Reference Include="zxing, Version=0.16.5.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
-      <HintPath>..\packages\ZXing.Net.0.16.5\lib\net47\zxing.dll</HintPath>
+    <Reference Include="zxing, Version=0.16.6.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
+      <HintPath>..\packages\ZXing.Net.0.16.6\lib\net47\zxing.dll</HintPath>
     </Reference>
-    <Reference Include="zxing.presentation, Version=0.16.5.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
-      <HintPath>..\packages\ZXing.Net.0.16.5\lib\net47\zxing.presentation.dll</HintPath>
+    <Reference Include="zxing.presentation, Version=0.16.6.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
+      <HintPath>..\packages\ZXing.Net.0.16.6\lib\net47\zxing.presentation.dll</HintPath>
     </Reference>
   </ItemGroup>
   <ItemGroup>
@@ -262,7 +262,6 @@
     </Compile>
     <Compile Include="Settings.cs" />
     <Compile Include="Controller\System\Hotkeys\Hotkeys.cs" />
-    <Compile Include="StringEx.cs" />
     <Compile Include="Util\ProcessManagement\Job.cs" />
     <Compile Include="Util\ProcessManagement\ThreadUtil.cs" />
     <Compile Include="Util\Sockets\LineReader.cs" />
@@ -427,14 +426,14 @@
   </ItemGroup>
   <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <Import Project="..\packages\Fody.4.2.1\build\Fody.targets" Condition="Exists('..\packages\Fody.4.2.1\build\Fody.targets')" />
+  <Import Project="..\packages\Fody.6.2.6\build\Fody.targets" Condition="Exists('..\packages\Fody.6.2.6\build\Fody.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('..\packages\Fody.4.2.1\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.4.2.1\build\Fody.targets'))" />
-    <Error Condition="!Exists('..\packages\Caseless.Fody.1.8.3\build\Caseless.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Caseless.Fody.1.8.3\build\Caseless.Fody.props'))" />
-    <Error Condition="!Exists('..\packages\Costura.Fody.3.3.3\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.3.3.3\build\Costura.Fody.props'))" />
+    <Error Condition="!Exists('..\packages\Fody.6.2.6\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.2.6\build\Fody.targets'))" />
+    <Error Condition="!Exists('..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Caseless.Fody.1.9.0\build\Caseless.Fody.props'))" />
+    <Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
   </Target>
   <!-- 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.
diff --git a/test/ShadowsocksTest.csproj b/test/ShadowsocksTest.csproj
index c21ab66b3..4d2640b73 100644
--- a/test/ShadowsocksTest.csproj
+++ b/test/ShadowsocksTest.csproj
@@ -69,6 +69,7 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
+    <None Include="app.config" />
     <None Include="packages.config" />
   </ItemGroup>
   <Choose>
diff --git a/test/app.config b/test/app.config
new file mode 100644
index 000000000..9f7e1f7a2
--- /dev/null
+++ b/test/app.config
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>
\ No newline at end of file