├── ErcTools ├── favicon.ico ├── App.xaml.cs ├── ViewModel │ ├── MainViewModel.cs │ └── ViewModelBase.cs ├── Command │ ├── CloseWindowsCommand.cs │ └── DelegateCommand.cs ├── ErcTools.csproj ├── App.xaml ├── MainWindow.xaml.cs └── MainWindow.xaml ├── WPF_Best_Hosts ├── favicon.ico ├── App.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Domain │ ├── DocumentationLinkType.cs │ ├── DocumentationLinks.xaml.cs │ ├── NotifyPropertyChangedExtension.cs │ ├── MainWindowViewModel.cs │ ├── AnotherCommandImplementation.cs │ ├── DemoItem.cs │ ├── DocumentationLink.cs │ └── DocumentationLinks.xaml ├── Behaviour │ ├── WebSpeedComparer.cs │ ├── ResponseComparer.cs │ └── DataGridSortBehavior.cs ├── App.xaml.cs ├── Model │ ├── UpdateDataParams.cs │ ├── HtmlSearch.cs │ ├── HostsData.cs │ └── PingData.cs ├── View │ ├── Home.xaml │ ├── Home.xaml.cs │ ├── HostsManage.xaml │ ├── HostsManage.xaml.cs │ ├── IPTest.xaml │ └── IPTest.xaml.cs ├── Converter │ └── InverseBoolConvert.cs ├── XamlDisplayEx.cs ├── packages.config ├── Lib │ ├── Utils.cs │ ├── HttpHelper.cs │ └── Hosts.cs ├── MainWindow.xaml.cs ├── MainWindow.xaml ├── App.xaml └── WPF_Best_Hosts.csproj ├── README.assets ├── 1561103527447.png ├── 1561103547373.png └── 1561103555928.png ├── Wpf_github_hosts ├── app.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── app.manifest │ └── Resources.resx ├── App.xaml.cs ├── LogHelper.cs ├── packages.config ├── HtmlSearch.cs ├── HttpHelper.cs ├── ProgressBarHelper.cs ├── App.xaml ├── Model.cs ├── Hosts.cs ├── MainWindow.xaml ├── Wpf_github_hosts.csproj └── MainWindow.xaml.cs ├── Wpf_github_hosts.sln.DotSettings ├── README.md ├── Wpf_github_hosts.sln └── .gitignore /ErcTools/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ercJuL/Wpf_github_hosts/HEAD/ErcTools/favicon.ico -------------------------------------------------------------------------------- /WPF_Best_Hosts/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ercJuL/Wpf_github_hosts/HEAD/WPF_Best_Hosts/favicon.ico -------------------------------------------------------------------------------- /README.assets/1561103527447.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ercJuL/Wpf_github_hosts/HEAD/README.assets/1561103527447.png -------------------------------------------------------------------------------- /README.assets/1561103547373.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ercJuL/Wpf_github_hosts/HEAD/README.assets/1561103547373.png -------------------------------------------------------------------------------- /README.assets/1561103555928.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ercJuL/Wpf_github_hosts/HEAD/README.assets/1561103555928.png -------------------------------------------------------------------------------- /Wpf_github_hosts/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/DocumentationLinkType.cs: -------------------------------------------------------------------------------- 1 | namespace WPF_Best_Hosts.Domain 2 | { 3 | public enum DocumentationLinkType 4 | { 5 | Wiki, 6 | DemoPageSource, 7 | ControlSource, 8 | StyleSource, 9 | Video 10 | } 11 | } -------------------------------------------------------------------------------- /Wpf_github_hosts/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Windows; 7 | 8 | namespace Wpf_github_hosts 9 | { 10 | /// 11 | /// App.xaml 的交互逻辑 12 | /// 13 | public partial class App : Application 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ErcTools/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace ErcTools 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/DocumentationLinks.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace WPF_Best_Hosts.Domain 4 | { 5 | /// 6 | /// Interaction logic for DocumentationLinks.xaml 7 | /// 8 | public partial class DocumentationLinks : UserControl 9 | { 10 | public DocumentationLinks() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Wpf_github_hosts.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True -------------------------------------------------------------------------------- /ErcTools/ViewModel/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using ErcTools.Command; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Windows; 6 | using System.Windows.Input; 7 | 8 | namespace ErcTools.ViewModel 9 | { 10 | public class MainViewModel: ViewModelBase 11 | { 12 | public ICommand CloseWindowsCommand { get; } 13 | public MainViewModel() 14 | { 15 | CloseWindowsCommand = new CloseWindowsCommand(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Behaviour/WebSpeedComparer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using WPF_Best_Hosts.Lib; 4 | 5 | namespace WPF_Best_Hosts.Behaviour 6 | { 7 | public class WebSpeedComparer : IComparer 8 | { 9 | public int Compare(object x, object y) 10 | { 11 | var xNum = Utils.InverseHumanReadableByteCount((string) x); 12 | var yNum = Utils.InverseHumanReadableByteCount((string) y); 13 | 14 | var result = xNum - yNum; 15 | return result == 0 ? 0 : (int) (Math.Abs(result) / result); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using ShowMeTheXAML; 9 | 10 | namespace WPF_Best_Hosts 11 | { 12 | /// 13 | /// App.xaml 的交互逻辑 14 | /// 15 | public partial class App : Application 16 | { 17 | protected override void OnStartup(StartupEventArgs e) 18 | { 19 | XamlDisplay.Init(); 20 | base.OnStartup(e); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Wpf_github_hosts/LogHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.CompilerServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | namespace Wpf_github_hosts 10 | { 11 | public static class LogHelper 12 | { 13 | public static TextBlock LableComponent { get; set; } 14 | 15 | public static void UpdateLog(string message) 16 | { 17 | if (LableComponent != null) 18 | { 19 | LableComponent.Text = message; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Model/UpdateDataParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace WPF_Best_Hosts.Model 8 | { 9 | public class UpdateDataParams 10 | { 11 | public UpdateDataParams(string guidLocalKey, string domain, string encode) 12 | { 13 | GuidLocalKey = guidLocalKey; 14 | Domain = domain; 15 | Encode = encode; 16 | } 17 | public string GuidLocalKey { get; set; } 18 | public string Domain { get; set; } 19 | public string Encode { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/View/Home.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/View/Home.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Shapes; 14 | 15 | namespace WPF_Best_Hosts.View 16 | { 17 | /// 18 | /// Home.xaml 的交互逻辑 19 | /// 20 | public partial class Home : UserControl 21 | { 22 | public Home() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Behaviour/ResponseComparer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using WPF_Best_Hosts.Lib; 9 | 10 | namespace WPF_Best_Hosts.Behaviour 11 | { 12 | public class ResponseComparer: IComparer 13 | { 14 | public int Compare(object x, object y) 15 | { 16 | var xNum = Utils.StringToNum(x); 17 | var yNum = Utils.StringToNum(y); 18 | 19 | var result = xNum - yNum; 20 | return result == 0 ? 0 : (int) (Math.Abs(result) / result); 21 | } 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Converter/InverseBoolConvert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace WPF_Best_Hosts.Converter 10 | { 11 | public class InverseBoolConvert: IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | return !(bool) value; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/XamlDisplayEx.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace WPF_Best_Hosts 5 | { 6 | public static class XamlDisplayEx 7 | { 8 | public static readonly DependencyProperty ButtonDockProperty = DependencyProperty.RegisterAttached( 9 | "ButtonDock", typeof(Dock), typeof(XamlDisplayEx), new PropertyMetadata(default(Dock))); 10 | 11 | public static void SetButtonDock(DependencyObject element, Dock value) 12 | { 13 | element.SetValue(ButtonDockProperty, value); 14 | } 15 | 16 | public static Dock GetButtonDock(DependencyObject element) 17 | { 18 | return (Dock) element.GetValue(ButtonDockProperty); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/NotifyPropertyChangedExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace WPF_Best_Hosts.Domain 7 | { 8 | public static class NotifyPropertyChangedExtension 9 | { 10 | public static void MutateVerbose(this INotifyPropertyChanged instance, ref TField field, TField newValue, Action raise, [CallerMemberName] string propertyName = null) 11 | { 12 | if (EqualityComparer.Default.Equals(field, newValue)) return; 13 | field = newValue; 14 | raise?.Invoke(new PropertyChangedEventArgs(propertyName)); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ErcTools/Command/CloseWindowsCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Input; 5 | using static System.Net.Mime.MediaTypeNames; 6 | using System; 7 | 8 | namespace ErcTools.Command 9 | { 10 | public class CloseWindowsCommand: ICommand 11 | { 12 | public event EventHandler CanExecuteChanged; 13 | 14 | public bool CanExecute(object parameter) 15 | { 16 | return true; 17 | } 18 | 19 | public void Execute(object parameter) 20 | { 21 | System.Windows.Application.Current.Shutdown(); 22 | } 23 | 24 | public void InvokeCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ErcTools/ErcTools.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | netcoreapp3.0 6 | true 7 | favicon.ico 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ErcTools/ViewModel/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Runtime.CompilerServices; 5 | using System.Text; 6 | 7 | namespace ErcTools.ViewModel 8 | { 9 | public abstract class ViewModelBase : INotifyPropertyChanged 10 | { 11 | public event PropertyChangedEventHandler PropertyChanged; 12 | 13 | protected bool SetProperty(ref T field, T newValue, [CallerMemberName]string propertyName = null) 14 | { 15 | if (!EqualityComparer.Default.Equals(field, newValue)) 16 | { 17 | field = newValue; 18 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 19 | return true; 20 | } 21 | return false; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Windows.Controls; 4 | using System.Windows.Documents; 5 | using MaterialDesignThemes.Wpf; 6 | using MaterialDesignThemes.Wpf.Transitions; 7 | using WPF_Best_Hosts.View; 8 | 9 | namespace WPF_Best_Hosts.Domain 10 | { 11 | public class MainWindowViewModel 12 | { 13 | public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue) 14 | { 15 | if (snackbarMessageQueue == null) throw new ArgumentNullException(nameof(snackbarMessageQueue)); 16 | 17 | DemoItems = new [] 18 | { 19 | new DemoItem("Home", new Home()), 20 | new DemoItem("IPTest", new IPTest()), 21 | new DemoItem("HostsManage", new HostsManage()), 22 | }; 23 | } 24 | 25 | public DemoItem[] DemoItems { get; } 26 | } 27 | } -------------------------------------------------------------------------------- /Wpf_github_hosts/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ErcTools/Command/DelegateCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Input; 5 | 6 | namespace ErcTools.Command 7 | { 8 | class DelegateCommand: ICommand 9 | { 10 | private readonly Action _executeAction; 11 | private readonly Func _canExecuteAction; 12 | 13 | public DelegateCommand(Action executeAction, Func canExecuteAction) 14 | { 15 | _executeAction = executeAction; 16 | _canExecuteAction = canExecuteAction; 17 | } 18 | 19 | public void Execute(object parameter) => _executeAction(parameter); 20 | public bool CanExecute(object parameter) => _canExecuteAction?.Invoke(parameter) ?? true; 21 | 22 | public event EventHandler CanExecuteChanged; 23 | public void InvokeCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Wpf_github_hosts.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/View/HostsManage.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WPF_Best_Hosts.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Wpf_github_hosts/HtmlSearch.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.InteropServices; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace Wpf_github_hosts 6 | { 7 | public class HtmlSearch 8 | { 9 | public HtmlSearch() 10 | { 11 | } 12 | 13 | public HtmlSearch(string html) 14 | { 15 | var html2 = Regex.Replace(html, "\\r", " "); 16 | html2 = Regex.Replace(html2, "\\n", " "); 17 | html2 = Regex.Replace(html2, "\\s{2,}", " "); 18 | GuidLocal = new Dictionary(); 19 | foreach (Match guidLocalMatch in Regex.Matches(html2, "
(.*?)
")) 20 | { 21 | GuidLocal.Add(guidLocalMatch.Groups[1].Value,guidLocalMatch.Groups[2].Value); 22 | } 23 | var encodeMatch = Regex.Match(html, ""); 24 | Encode = encodeMatch.Groups[1].Value; 25 | if (Encode=="") 26 | { 27 | return; 28 | } 29 | } 30 | 31 | public Dictionary GuidLocal { get; set; } 32 | public string Encode { get; set; } 33 | } 34 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/Model/HtmlSearch.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.InteropServices; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace Wpf_github_hosts 6 | { 7 | public class HtmlSearch 8 | { 9 | public HtmlSearch() 10 | { 11 | } 12 | 13 | public HtmlSearch(string html) 14 | { 15 | var html2 = Regex.Replace(html, "\\r", " "); 16 | html2 = Regex.Replace(html2, "\\n", " "); 17 | html2 = Regex.Replace(html2, "\\s{2,}", " "); 18 | GuidLocal = new Dictionary(); 19 | foreach (Match guidLocalMatch in Regex.Matches(html2, "
(.*?)
")) 20 | { 21 | GuidLocal.Add(guidLocalMatch.Groups[1].Value,guidLocalMatch.Groups[2].Value); 22 | } 23 | var encodeMatch = Regex.Match(html, ""); 24 | Encode = encodeMatch.Groups[1].Value; 25 | if (Encode=="") 26 | { 27 | return; 28 | } 29 | } 30 | 31 | public Dictionary GuidLocal { get; set; } 32 | public string Encode { get; set; } 33 | } 34 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > 别fork, 别start了, 已经停止开发了 2 | > 相关加速方法 3 | > https://steampp.net/ 4 | > https://greasyfork.org/zh-CN/scripts/412245-github-%E5%A2%9E%E5%BC%BA-%E9%AB%98%E9%80%9F%E4%B8%8B%E8%BD%BD 5 | > 本项目原理: https://zhuanlan.zhihu.com/p/107334179 6 | > https://www.bilibili.com/read/cv10607526/ 7 | 8 | 9 | # **Wpf_github_hosts** 10 | 11 | > 明年(也)一定完(不)成(:cry:) 12 | 13 | 解决访问GitHub慢的问题 14 | 15 | - 需要管理员权限,如果要改hosts 16 | 17 | 18 | 19 | ![1561103527447](README.assets/1561103527447.png) 20 | 21 | 22 | 23 | ![1561103547373](README.assets/1561103547373.png) 24 | 25 | 26 | 27 | ![1561103555928](README.assets/1561103555928.png) 28 | 29 | 30 | 31 | TODO List 32 | 33 | - [x] 同一个ip只次ping 34 | 35 | - [ ] 检测进度显示 36 | 37 | > 目前计划这个想砍了 38 | 39 | - 进度条显示 :persevere: 40 | - 进度条精确显示:persevere: 41 | - 更精细的进度条显示:persevere: 42 | 43 | - [x] hosts管理 44 | - 添加hosts:white_check_mark: 45 | - 更新hosts:white_check_mark: 46 | - 删除hosts:white_check_mark: 47 | - 显示已有hosts:white_check_mark: 48 | 49 | - [ ] 运行信息显示 50 | - 简短正在运行信息显示:white_check_mark: 51 | - 详细信息显示:neutral_face: 52 | - error信息显示:neutral_face: 53 | 54 | - [x] UI美化 55 | 56 | - [x] 非致命性hosts文件出错修复 57 | 58 | - [x] TCP/IP 测试 59 | 60 | - [ ] 酸酸乳 批量测试 61 | 62 | - 批量ip导入 63 | 64 | - [ ] 测试任务可停止 65 | 66 | - [ ] 测试线路可选择 67 | 68 | - [ ] 配置文件 69 | 70 | - 存于自身:bangbang: 71 | - 存于配置文件:bangbang: 72 | -------------------------------------------------------------------------------- /Wpf_github_hosts/HttpHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Flurl; 7 | using Flurl.Http; 8 | 9 | namespace Wpf_github_hosts 10 | { 11 | public static class HttpHelper 12 | { 13 | public static async Task GetHtmlTask(string postUrl, string pathSegment, object formData) 14 | { 15 | var responeseHtml = await postUrl.AppendPathSegment(pathSegment) 16 | .WithTimeout(10000) 17 | .WithHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36") 18 | .PostUrlEncodedAsync(formData) 19 | .ReceiveString(); 20 | return responeseHtml; 21 | } 22 | 23 | public static string GetPingDataTask(string postUrl, string pathSegment, object formData) 24 | { 25 | var responseJson = postUrl.AppendPathSegment(pathSegment).SetQueryParam("t=ping").WithTimeout(10000) 26 | .WithHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36") 27 | .PostUrlEncodedAsync(formData) 28 | .ReceiveString(); 29 | return responseJson.Result; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/Model/HostsData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WPF_Best_Hosts.Model 9 | { 10 | public class HostsData : INotifyPropertyChanged 11 | { 12 | private string _ip; 13 | private string _domain; 14 | private string _state; 15 | 16 | public string Ip 17 | { 18 | get => _ip; 19 | set 20 | { 21 | _ip = value; 22 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Ip")); 23 | } 24 | } 25 | 26 | public string Domain 27 | { 28 | get => _domain; 29 | set 30 | { 31 | _domain = value; 32 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Domain")); 33 | } 34 | } 35 | 36 | public string State 37 | { 38 | get => _state; 39 | set 40 | { 41 | _state = value; 42 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("State")); 43 | } 44 | } 45 | 46 | public event PropertyChangedEventHandler PropertyChanged; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Lib/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace WPF_Best_Hosts.Lib 5 | { 6 | public static class Utils 7 | { 8 | public static string HumanReadableByteCount(long bytes, bool isDa) 9 | { 10 | var unit = isDa ? 1000 : 1024; 11 | if (bytes < unit) return bytes + " B"; 12 | var exp = (int) (Math.Log(bytes) / Math.Log(unit)); 13 | var pre = (isDa ? "kMGTPE" : "KMGTPE")[exp - 1] + (isDa ? "" : "i"); 14 | return string.Format("{0:F1} {1}B", bytes / Math.Pow(unit, exp), pre); 15 | } 16 | 17 | public static long InverseHumanReadableByteCount(string hrString) 18 | { 19 | var pre = Regex.Match(hrString, " [KMGTPE]?i?B", RegexOptions.IgnoreCase); 20 | if (!pre.Success) return -1; 21 | var num = Convert.ToDouble(hrString.TrimStart().Split(' ')[0]); 22 | var preStr = pre.Value.Trim().ToUpper(); 23 | if (preStr == "B") return (long) num; 24 | var unit = preStr.Contains("i") ? 1024 : 1000; 25 | var exp = "KMGTPE".IndexOf(preStr[0]) + 1; 26 | return (long) (num * Math.Pow(unit, exp)); 27 | } 28 | 29 | public static decimal StringToNum(object x) 30 | { 31 | var strX = Regex.Replace((string) x, @"[^\d.\d]", ""); 32 | if (Regex.IsMatch(strX, @"^[+-]?\d+[.]?\d*$")) return decimal.Parse(strX); 33 | return decimal.MaxValue; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Wpf_github_hosts/ProgressBarHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | using System.Windows; 5 | using Wpf_github_hosts.Annotations; 6 | 7 | namespace Wpf_github_hosts 8 | { 9 | public class ProgressBarHelper:INotifyPropertyChanged 10 | { 11 | private double _valueMax; 12 | private double _valueNow; 13 | 14 | public double ValueMax 15 | { 16 | get => _valueMax; 17 | set 18 | { 19 | _valueMax = value; 20 | _valueNow=0; 21 | UpdateUi("ValueMax"); 22 | } 23 | } 24 | 25 | public double ValueNow 26 | { 27 | get => Math.Round(_valueNow * 100 / ValueMax, 2); 28 | set 29 | { 30 | _valueNow=value; 31 | UpdateUi("ValueNow"); 32 | } 33 | } 34 | 35 | public void Step() 36 | { 37 | _valueNow++; 38 | UpdateUi("ValueNow"); 39 | } 40 | 41 | public Visibility Visibility => Math.Abs(_valueMax - _valueNow) > 0 ? Visibility.Visible : Visibility.Hidden; 42 | public event PropertyChangedEventHandler PropertyChanged; 43 | 44 | private void UpdateUi(string name) 45 | { 46 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 47 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PerceentString")); 48 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Visibility")); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/AnotherCommandImplementation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace WPF_Best_Hosts.Domain 5 | { 6 | /// 7 | /// No WPF project is complete without it's own version of this. 8 | /// 9 | public class AnotherCommandImplementation : ICommand 10 | { 11 | private readonly Action _execute; 12 | private readonly Func _canExecute; 13 | 14 | public AnotherCommandImplementation(Action execute) : this(execute, null) 15 | { 16 | } 17 | 18 | public AnotherCommandImplementation(Action execute, Func canExecute) 19 | { 20 | if (execute == null) throw new ArgumentNullException(nameof(execute)); 21 | 22 | _execute = execute; 23 | _canExecute = canExecute ?? (x => true); 24 | } 25 | 26 | public bool CanExecute(object parameter) 27 | { 28 | return _canExecute(parameter); 29 | } 30 | 31 | public void Execute(object parameter) 32 | { 33 | _execute(parameter); 34 | } 35 | 36 | public event EventHandler CanExecuteChanged 37 | { 38 | add 39 | { 40 | CommandManager.RequerySuggested += value; 41 | } 42 | remove 43 | { 44 | CommandManager.RequerySuggested -= value; 45 | } 46 | } 47 | 48 | public void Refresh() 49 | { 50 | CommandManager.InvalidateRequerySuggested(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // 有关程序集的一般信息由以下 8 | // 控制。更改这些特性值可修改 9 | // 与程序集关联的信息。 10 | [assembly: AssemblyTitle("WPF_Best_Hosts")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("WPF_Best_Hosts")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // 将 ComVisible 设置为 false 会使此程序集中的类型 20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | //若要开始生成可本地化的应用程序,请设置 25 | //.csproj 文件中的 CultureYouAreCodingWith 26 | //例如,如果您在源文件中使用的是美国英语, 27 | //使用的是美国英语,请将 设置为 en-US。 然后取消 28 | //对以下 NeutralResourceLanguage 特性的注释。 更新 29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置 36 | //(未在页面中找到资源时使用, 37 | //或应用程序资源字典中找到时使用) 38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 39 | //(未在页面中找到资源时使用, 40 | //、应用程序或任何主题专用资源字典中找到时使用) 41 | )] 42 | 43 | 44 | // 程序集的版本信息由下列四个值组成: 45 | // 46 | // 主版本 47 | // 次版本 48 | // 生成号 49 | // 修订号 50 | // 51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 52 | //通过使用 "*",如下所示: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // 有关程序集的一般信息由以下 8 | // 控制。更改这些特性值可修改 9 | // 与程序集关联的信息。 10 | [assembly: AssemblyTitle("Wpf_github_hosts")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("Wpf_github_hosts")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // 将 ComVisible 设置为 false 会使此程序集中的类型 20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | //若要开始生成可本地化的应用程序,请设置 25 | //.csproj 文件中的 CultureYouAreCodingWith 26 | //例如,如果您在源文件中使用的是美国英语, 27 | //使用的是美国英语,请将 设置为 en-US。 然后取消 28 | //对以下 NeutralResourceLanguage 特性的注释。 更新 29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置 36 | //(未在页面中找到资源时使用, 37 | //或应用程序资源字典中找到时使用) 38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 39 | //(未在页面中找到资源时使用, 40 | //、应用程序或任何主题专用资源字典中找到时使用) 41 | )] 42 | 43 | 44 | // 程序集的版本信息由下列四个值组成: 45 | // 46 | // 主版本 47 | // 次版本 48 | // 生成号 49 | // 修订号 50 | // 51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 52 | //通过使用 "*",如下所示: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /ErcTools/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Lib/HttpHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.RegularExpressions; 4 | using System.Threading.Tasks; 5 | using Flurl; 6 | using Flurl.Http; 7 | using Wpf_github_hosts; 8 | 9 | namespace WPF_Best_Hosts.Lib 10 | { 11 | public static class HttpHelper 12 | { 13 | public static HtmlSearch GetHtmlTask(string postUrl, string pathSegment, object formData) 14 | { 15 | var responseHtml = postUrl.AppendPathSegment(pathSegment) 16 | .WithTimeout(10000) 17 | .WithHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36") 18 | .PostUrlEncodedAsync(formData) 19 | .ReceiveString(); 20 | return new HtmlSearch(responseHtml.Result); 21 | } 22 | 23 | public static string GetPingDataTask(string postUrl, string pathSegment, object formData) 24 | { 25 | var responseJson = postUrl.AppendPathSegment(pathSegment).SetQueryParam("t=ping").WithTimeout(10000) 26 | .WithHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36") 27 | .PostUrlEncodedAsync(formData) 28 | .ReceiveString(); 29 | return responseJson.Result; 30 | } 31 | 32 | public static void TcpIpTest(string ip, string host, out int timeConsume, out int dSize) 33 | { 34 | var start = DateTime.UtcNow; 35 | var test = $"http://{ip}".WithHeaders(new 36 | { 37 | User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 38 | Host = host 39 | }).GetStringAsync(); 40 | var test2 = test.Result; 41 | timeConsume = (DateTime.UtcNow - start).Milliseconds; 42 | dSize = test2.Length; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Wpf_github_hosts.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29009.5 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wpf_github_hosts", "Wpf_github_hosts\Wpf_github_hosts.csproj", "{03638F45-217A-4A14-B27B-F8C2D75D792A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPF_Best_Hosts", "WPF_Best_Hosts\WPF_Best_Hosts.csproj", "{77476A58-9274-4963-A2EF-5451CF6CA210}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ErcTools", "ErcTools\ErcTools.csproj", "{4A39B7C9-4CAD-46E6-8623-D380C8EE9150}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {03638F45-217A-4A14-B27B-F8C2D75D792A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {03638F45-217A-4A14-B27B-F8C2D75D792A}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {03638F45-217A-4A14-B27B-F8C2D75D792A}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {03638F45-217A-4A14-B27B-F8C2D75D792A}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {77476A58-9274-4963-A2EF-5451CF6CA210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {77476A58-9274-4963-A2EF-5451CF6CA210}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {77476A58-9274-4963-A2EF-5451CF6CA210}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {77476A58-9274-4963-A2EF-5451CF6CA210}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {4A39B7C9-4CAD-46E6-8623-D380C8EE9150}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {4A39B7C9-4CAD-46E6-8623-D380C8EE9150}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {4A39B7C9-4CAD-46E6-8623-D380C8EE9150}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {4A39B7C9-4CAD-46E6-8623-D380C8EE9150}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {D966DBF2-3D28-433F-A40B-3091B22BABDC} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/DemoItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | 7 | namespace WPF_Best_Hosts.Domain 8 | { 9 | public class DemoItem : INotifyPropertyChanged 10 | { 11 | private string _name; 12 | private object _content; 13 | private ScrollBarVisibility _horizontalScrollBarVisibilityRequirement; 14 | private ScrollBarVisibility _verticalScrollBarVisibilityRequirement; 15 | private Thickness _marginRequirement = new Thickness(16); 16 | 17 | public DemoItem(string name, object content) 18 | { 19 | _name = name; 20 | Content = content; 21 | } 22 | 23 | public string Name 24 | { 25 | get { return _name; } 26 | set { this.MutateVerbose(ref _name, value, RaisePropertyChanged()); } 27 | } 28 | 29 | public object Content 30 | { 31 | get { return _content; } 32 | set { this.MutateVerbose(ref _content, value, RaisePropertyChanged()); } 33 | } 34 | 35 | public ScrollBarVisibility HorizontalScrollBarVisibilityRequirement 36 | { 37 | get { return _horizontalScrollBarVisibilityRequirement; } 38 | set { this.MutateVerbose(ref _horizontalScrollBarVisibilityRequirement, value, RaisePropertyChanged()); } 39 | } 40 | 41 | public ScrollBarVisibility VerticalScrollBarVisibilityRequirement 42 | { 43 | get { return _verticalScrollBarVisibilityRequirement; } 44 | set { this.MutateVerbose(ref _verticalScrollBarVisibilityRequirement, value, RaisePropertyChanged()); } 45 | } 46 | 47 | public Thickness MarginRequirement 48 | { 49 | get { return _marginRequirement; } 50 | set { this.MutateVerbose(ref _marginRequirement, value, RaisePropertyChanged()); } 51 | } 52 | 53 | public event PropertyChangedEventHandler PropertyChanged; 54 | 55 | private Action RaisePropertyChanged() 56 | { 57 | return args => PropertyChanged?.Invoke(this, args); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/View/HostsManage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | using WPF_Best_Hosts.Lib; 17 | using WPF_Best_Hosts.Model; 18 | 19 | namespace WPF_Best_Hosts.View 20 | { 21 | /// 22 | /// HostsManage.xaml 的交互逻辑 23 | /// 24 | public partial class HostsManage : UserControl 25 | { 26 | public HostsManage() 27 | { 28 | InitializeComponent(); 29 | Hosts.InitHostsData(); 30 | HostsDataGrid.ItemsSource = Hosts.hostsDatas; 31 | } 32 | private void HostsDataGrid_OnMouseDoubleClick(object sender, MouseButtonEventArgs e) 33 | { 34 | DataGrid datagrid = sender as DataGrid; 35 | var cell = datagrid.CurrentCell; 36 | var item = cell.Item as HostsData; 37 | 38 | if (item != null && cell.Column.DisplayIndex == 2) 39 | { 40 | item.State = item.State == "激活" ? "失效" : "激活"; 41 | var hostsTxt = (item.State == "激活" ? "" : "#") + item.Ip + " " + item.Domain; 42 | Hosts.updateHosts(hostsTxt); 43 | } 44 | } 45 | 46 | private void HostsDataGrid_OnCellEditEnding(object sender, DataGridCellEditEndingEventArgs e) 47 | { 48 | string newValue = (e.EditingElement as TextBox).Text; 49 | var item = e.Row.Item as HostsData; 50 | if (Regex.IsMatch(newValue, "\\d+\\.\\d+\\.\\d+\\.\\d+")) 51 | { 52 | var hostsTxt = (item.State == "激活" ? "" : "#") + newValue + " " + item.Domain; 53 | Hosts.updateHosts(hostsTxt); 54 | } 55 | else if (Regex.IsMatch(newValue, "[\\.\\w]+")) 56 | { 57 | var hostsTxt = (item.State == "激活" ? "" : "#") + item.Ip + " " + newValue; 58 | Hosts.updateHosts(hostsTxt); 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Wpf_github_hosts/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Wpf_github_hosts.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wpf_github_hosts.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本: 4.0.30319.42000 5 | // 6 | // 对此文件的更改可能导致不正确的行为,如果 7 | // 重新生成代码,则所做更改将丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WPF_Best_Hosts.Properties 12 | { 13 | 14 | 15 | /// 16 | /// 强类型资源类,用于查找本地化字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// 返回此类使用的缓存 ResourceManager 实例。 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WPF_Best_Hosts.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// 覆盖当前线程的 CurrentUICulture 属性 56 | /// 使用此强类型的资源类的资源查找。 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ErcTools/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using ErcTools.ViewModel; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace ErcTools 18 | { 19 | /// 20 | /// Interaction logic for MainWindow.xaml 21 | /// 22 | public partial class MainWindow : Window 23 | { 24 | private bool mRestoreForDragMove; 25 | public MainWindow() 26 | { 27 | var mainViewModel = new MainViewModel(); 28 | DataContext = mainViewModel; 29 | InitializeComponent(); 30 | 31 | } 32 | 33 | private void Window_StateChanged(object sender, EventArgs e) 34 | { 35 | switch (this.WindowState) 36 | { 37 | case WindowState.Maximized: 38 | this.MaxWidth = SystemParameters.WorkArea.Width + 16; 39 | this.MaxHeight = SystemParameters.WorkArea.Height + 16; 40 | this.BorderThickness = new Thickness(5); 41 | break; 42 | case WindowState.Normal: 43 | this.BorderThickness = new Thickness(0); 44 | break; 45 | } 46 | } 47 | private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 48 | { 49 | 50 | if (e.ClickCount == 2) 51 | { 52 | if (ResizeMode != ResizeMode.CanResize && ResizeMode != ResizeMode.CanResizeWithGrip) return; 53 | WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; 54 | } 55 | else 56 | { 57 | mRestoreForDragMove = WindowState == WindowState.Maximized; 58 | DragMove(); 59 | } 60 | } 61 | private void OnMouseMove(object sender, MouseEventArgs e) 62 | { 63 | if (mRestoreForDragMove) 64 | { 65 | mRestoreForDragMove = false; 66 | WindowState = WindowState.Normal; 67 | //var point = e.MouseDevice.GetPosition(this); 68 | // Left = point.X - ClientGrid.ActualWidth * point.X / SystemParameters.WorkArea.Width - WindowShadowBorder.Margin.Left; 69 | // Top = point.Y - ClientGrid.ActualHeight * point.Y / SystemParameters.WorkArea.Height - WindowShadowBorder.Margin.Top; 70 | //DragMove(); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Properties/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 55 | 56 | 70 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/DocumentationLink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Windows.Controls; 4 | using System.Windows.Input; 5 | 6 | namespace WPF_Best_Hosts.Domain 7 | { 8 | public class DocumentationLink 9 | { 10 | public DocumentationLink(DocumentationLinkType type, string url) : this(type, url, null) 11 | { 12 | } 13 | 14 | public DocumentationLink(DocumentationLinkType type, string url, string label) 15 | { 16 | Label = label ?? type.ToString(); 17 | Url = url; 18 | Type = type; 19 | Open = new AnotherCommandImplementation(Execute); 20 | } 21 | 22 | public static DocumentationLink WikiLink(string page, string label) 23 | { 24 | return new DocumentationLink(DocumentationLinkType.Wiki, 25 | $"{ConfigurationManager.AppSettings["GitHub"]}/wiki/" + page, label); 26 | } 27 | 28 | public static DocumentationLink StyleLink(string nameChunk) 29 | { 30 | return new DocumentationLink( 31 | DocumentationLinkType.StyleSource, 32 | $"{ConfigurationManager.AppSettings["GitHub"]}/blob/master/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.{nameChunk}.xaml", 33 | nameChunk); 34 | } 35 | 36 | public static DocumentationLink ApiLink(string subNamespace) 37 | { 38 | var typeName = typeof(TClass).Name; 39 | 40 | return new DocumentationLink( 41 | DocumentationLinkType.ControlSource, 42 | $"{ConfigurationManager.AppSettings["GitHub"]}/blob/master/MaterialDesignThemes.Wpf/{subNamespace}/{typeName}.cs", 43 | typeName); 44 | } 45 | 46 | 47 | public static DocumentationLink ApiLink() 48 | { 49 | return ApiLink(typeof(TClass)); 50 | } 51 | 52 | public static DocumentationLink ApiLink(Type type) 53 | { 54 | var typeName = type.Name; 55 | 56 | return new DocumentationLink( 57 | DocumentationLinkType.ControlSource, 58 | $"{ConfigurationManager.AppSettings["GitHub"]}/blob/master/MaterialDesignThemes.Wpf/{typeName}.cs", 59 | typeName); 60 | } 61 | 62 | public static DocumentationLink DemoPageLink() 63 | { 64 | return DemoPageLink(null); 65 | } 66 | 67 | public static DocumentationLink DemoPageLink(string label) 68 | { 69 | return DemoPageLink(label, null); 70 | } 71 | 72 | public static DocumentationLink DemoPageLink(string label, string nameSpace) 73 | { 74 | var ext = typeof(UserControl).IsAssignableFrom(typeof(TDemoPage)) 75 | ? "xaml" 76 | : "cs"; 77 | 78 | 79 | return new DocumentationLink( 80 | DocumentationLinkType.DemoPageSource, 81 | $"{ConfigurationManager.AppSettings["GitHub"]}/blob/master/MainDemo.Wpf/{(string.IsNullOrWhiteSpace(nameSpace) ? "" : ("/" + nameSpace + "/" ))}{typeof(TDemoPage).Name}.{ext}", 82 | label ?? typeof(TDemoPage).Name); 83 | } 84 | 85 | public string Label { get; } 86 | 87 | public string Url { get; } 88 | 89 | public DocumentationLinkType Type { get; } 90 | 91 | public ICommand Open { get; } 92 | 93 | private void Execute(object o) 94 | { 95 | System.Diagnostics.Process.Start(Url); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Controls.Primitives; 10 | using System.Windows.Data; 11 | using System.Windows.Documents; 12 | using System.Windows.Input; 13 | using System.Windows.Media; 14 | using System.Windows.Media.Imaging; 15 | using System.Windows.Navigation; 16 | using System.Windows.Shapes; 17 | using MaterialDesignThemes.Wpf; 18 | using WPF_Best_Hosts.Domain; 19 | using Flurl; 20 | using Flurl.Http; 21 | 22 | namespace WPF_Best_Hosts 23 | { 24 | /// 25 | /// MainWindow.xaml 的交互逻辑 26 | /// 27 | public partial class MainWindow : Window 28 | { 29 | public static Snackbar Snackbar; 30 | private bool mRestoreForDragMove; 31 | public MainWindow() 32 | { 33 | InitializeComponent(); 34 | this.MouseLeftButtonUp += (s, e) => { mRestoreForDragMove = false; }; 35 | Task.Factory.StartNew(() => 36 | { 37 | Thread.Sleep(2500); 38 | }).ContinueWith(t => 39 | { 40 | MainSnackbar.MessageQueue.Enqueue("欢迎使用"); 41 | }, TaskScheduler.FromCurrentSynchronizationContext()); 42 | 43 | DataContext = new MainWindowViewModel(MainSnackbar.MessageQueue); 44 | 45 | Snackbar = this.MainSnackbar; 46 | 47 | var start = DateTime.UtcNow; 48 | var test = $"http://192.30.253.113".WithHeaders(new 49 | { 50 | User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 51 | Host = "github.com" 52 | }).GetStringAsync(); 53 | var test2 = test.Result; 54 | } 55 | 56 | private void UIElement_OnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 57 | { 58 | //until we had a StaysOpen glag to Drawer, this will help with scroll bars 59 | var dependencyObject = Mouse.Captured as DependencyObject; 60 | while (dependencyObject != null) 61 | { 62 | if (dependencyObject is ScrollBar) return; 63 | dependencyObject = VisualTreeHelper.GetParent(dependencyObject); 64 | } 65 | 66 | MenuToggleButton.IsChecked = false; 67 | } 68 | 69 | private void Window_StateChanged(object sender, EventArgs e) 70 | { 71 | switch (this.WindowState) 72 | { 73 | case WindowState.Maximized: 74 | this.MaxWidth = SystemParameters.WorkArea.Width + 16; 75 | this.MaxHeight = SystemParameters.WorkArea.Height + 16; 76 | this.BorderThickness = new Thickness(5); //最大化后需要调整 77 | // WindowShadowBorder.Margin = new Thickness(0); 78 | break; 79 | case WindowState.Normal: 80 | this.BorderThickness = new Thickness(0); 81 | // WindowShadowBorder.Margin = new Thickness(10); 82 | break; 83 | } 84 | } 85 | private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 86 | { 87 | 88 | if (e.ClickCount == 2) 89 | { 90 | if (ResizeMode != ResizeMode.CanResize && ResizeMode != ResizeMode.CanResizeWithGrip) return; 91 | WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; 92 | } 93 | else 94 | { 95 | mRestoreForDragMove = WindowState == WindowState.Maximized; 96 | DragMove(); 97 | } 98 | } 99 | private void OnMouseMove(object sender, MouseEventArgs e) 100 | { 101 | if (mRestoreForDragMove) 102 | { 103 | mRestoreForDragMove = false; 104 | WindowState = WindowState.Normal; 105 | var point = e.MouseDevice.GetPosition(this); 106 | // Left = point.X - ClientGrid.ActualWidth * point.X / SystemParameters.WorkArea.Width - WindowShadowBorder.Margin.Left; 107 | // Top = point.Y - ClientGrid.ActualHeight * point.Y / SystemParameters.WorkArea.Height - WindowShadowBorder.Margin.Top; 108 | DragMove(); 109 | } 110 | } 111 | 112 | private void CloseButton_OnClick(object sender, RoutedEventArgs e) 113 | { 114 | Application.Current.Shutdown(); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Domain/DocumentationLinks.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Model/PingData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using WPF_Best_Hosts.Lib; 9 | 10 | namespace WPF_Best_Hosts.Model 11 | { 12 | public class PingData : INotifyPropertyChanged 13 | { 14 | private string _localName=""; 15 | private string _ip = ""; 16 | private string _ipLocal = ""; 17 | private string _answerTime = ""; 18 | private string _localAnswerTime = ""; 19 | private string _answerTtl = ""; 20 | private string _localAnswerTtl = ""; 21 | private int _timeConsume; 22 | private int _dSize; 23 | private string _tcpIpResult; 24 | public event PropertyChangedEventHandler PropertyChanged; 25 | 26 | public PingData() 27 | { 28 | } 29 | 30 | public PingData(string localGuid, string localName, string domain) 31 | { 32 | LocalName = localName; 33 | LocalGuid = localGuid; 34 | Domain = domain; 35 | } 36 | 37 | public string LocalName 38 | { 39 | get => _localName; 40 | set 41 | { 42 | _localName = value; 43 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocalName")); 44 | } 45 | } 46 | 47 | public string Ip 48 | { 49 | get => _ip; 50 | set 51 | { 52 | _ip = value; 53 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Ip")); 54 | } 55 | } 56 | 57 | public string IpLocal 58 | { 59 | get => _ipLocal; 60 | set 61 | { 62 | _ipLocal = value; 63 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IpLocal")); 64 | } 65 | } 66 | 67 | public string AnswerTime 68 | { 69 | get => _answerTime; 70 | set 71 | { 72 | _answerTime = value; 73 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AnswerTime")); 74 | } 75 | } 76 | 77 | public string LocalAnswerTime 78 | { 79 | get => _localAnswerTime; 80 | set 81 | { 82 | _localAnswerTime = Regex.IsMatch(value, "^\\d+$") ? value + " 毫秒" : value; 83 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocalAnswerTime")); 84 | } 85 | } 86 | 87 | public string AnswerTtl 88 | { 89 | get => _answerTtl; 90 | set 91 | { 92 | _answerTtl = value; 93 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AnswerTtl")); 94 | } 95 | } 96 | 97 | public string LocalAnswerTtl 98 | { 99 | get => _localAnswerTtl; 100 | set 101 | { 102 | _localAnswerTtl = value; 103 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocalAnswerTtl")); 104 | } 105 | } 106 | 107 | public string TcpIpResult 108 | { 109 | get => _tcpIpResult; 110 | set 111 | { 112 | _tcpIpResult = value; 113 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TcpIpResult")); 114 | } 115 | } 116 | 117 | public string TcpIpResultTip => $"下载{Utils.HumanReadableByteCount(DSize, false)}\n共耗时{TimeConsume}毫秒"; 118 | public int TimeConsume 119 | { 120 | get => _timeConsume; 121 | set 122 | { 123 | _timeConsume = value; 124 | if (_dSize > 0 && _timeConsume > 0) 125 | { 126 | _tcpIpResult = $"{Utils.HumanReadableByteCount(DSize / TimeConsume * 1000, false)}/s"; 127 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TcpIpResult")); 128 | } 129 | } 130 | } 131 | 132 | public int DSize 133 | { 134 | get => _dSize; 135 | set 136 | { 137 | _dSize = value; 138 | if (_timeConsume > 0 && _dSize > 0) 139 | { 140 | _tcpIpResult = $"{Utils.HumanReadableByteCount(DSize / TimeConsume * 1000, false)}/s"; 141 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TcpIpResult")); 142 | } 143 | } 144 | } 145 | 146 | public string LocalGuid { get; set; } 147 | public string Domain { get; set; } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Model.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Runtime.CompilerServices; 5 | using System.Text.RegularExpressions; 6 | using System.Windows; 7 | using Wpf_github_hosts.Annotations; 8 | 9 | namespace Wpf_github_hosts 10 | { 11 | public partial class MainWindow 12 | { 13 | public class PingData : INotifyPropertyChanged 14 | { 15 | private string _localName; 16 | private string _ip; 17 | private string _ipLocal; 18 | private string _answerTime; 19 | private string _localAnswerTime; 20 | private string _answerTtl; 21 | private string _localAnswerTtl; 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | 24 | public PingData() 25 | { 26 | } 27 | 28 | public PingData(string localGuid, string localName, string domain) 29 | { 30 | LocalName = localName; 31 | LocalGuid = localGuid; 32 | Domain = domain; 33 | } 34 | 35 | public string LocalName 36 | { 37 | get => _localName; 38 | set 39 | { 40 | _localName = value; 41 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocalName")); 42 | } 43 | } 44 | 45 | public string Ip 46 | { 47 | get => _ip; 48 | set 49 | { 50 | _ip = value; 51 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Ip")); 52 | } 53 | } 54 | 55 | public string IpLocal 56 | { 57 | get => _ipLocal; 58 | set 59 | { 60 | _ipLocal = value; 61 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IpLocal")); 62 | } 63 | } 64 | 65 | public string AnswerTime 66 | { 67 | get => _answerTime; 68 | set 69 | { 70 | _answerTime = value; 71 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AnswerTime")); 72 | } 73 | } 74 | 75 | public string LocalAnswerTime 76 | { 77 | get => _localAnswerTime; 78 | set 79 | { 80 | _localAnswerTime = Regex.IsMatch(value,"^\\d+$")?value + " 毫秒" :value; 81 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocalAnswerTime")); 82 | } 83 | } 84 | 85 | public string AnswerTtl 86 | { 87 | get => _answerTtl; 88 | set 89 | { 90 | _answerTtl = value; 91 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("AnswerTtl")); 92 | } 93 | } 94 | 95 | public string LocalAnswerTtl 96 | { 97 | get => _localAnswerTtl; 98 | set 99 | { 100 | _localAnswerTtl = value; 101 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LocalAnswerTtl")); 102 | } 103 | } 104 | 105 | public string LocalGuid { get; set; } 106 | public string Domain { get; set; } 107 | } 108 | 109 | public class PingPercentClass : INotifyPropertyChanged 110 | { 111 | private double _pingPercentData; 112 | 113 | public PingPercentClass(Double pingPercentData) 114 | { 115 | PingPercentData = pingPercentData; 116 | } 117 | public double PingPercentData 118 | { 119 | get => _pingPercentData; 120 | set 121 | { 122 | _pingPercentData = value; 123 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PingPercentData")); 124 | } 125 | } 126 | 127 | public event PropertyChangedEventHandler PropertyChanged; 128 | } 129 | 130 | private class UpdateDataParams 131 | { 132 | public UpdateDataParams(string guidLocalKey, string domain, string encode) 133 | { 134 | GuidLocalKey = guidLocalKey; 135 | Domain = domain; 136 | Encode = encode; 137 | } 138 | public string GuidLocalKey { get; set; } 139 | public string Domain { get; set; } 140 | public string Encode { get; set; } 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /ErcTools/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 33 | 42 | 43 | 44 | 45 | 47 | 48 | 49 | 51 | 54 | 最快节点测试工具 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 69 | 70 | 71 | 72 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Behaviour/DataGridSortBehavior.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.ComponentModel; 4 | using System.Reflection; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Data; 8 | 9 | namespace WPF_Best_Hosts.Behaviour 10 | { 11 | // https://stackoverflow.com/questions/18122751/wpf-datagrid-customsort-for-each-column/18218963#18218963 12 | public class DataGridSortBehavior 13 | { 14 | public static IComparer GetSorter(DataGridColumn column) 15 | { 16 | return (IComparer)column.GetValue(SorterProperty); 17 | } 18 | 19 | public static void SetSorter(DataGridColumn column, IComparer value) 20 | { 21 | column.SetValue(SorterProperty, value); 22 | } 23 | 24 | public static bool GetAllowCustomSort(DataGrid grid) 25 | { 26 | return (bool)grid.GetValue(AllowCustomSortProperty); 27 | } 28 | 29 | public static void SetAllowCustomSort(DataGrid grid, bool value) 30 | { 31 | grid.SetValue(AllowCustomSortProperty, value); 32 | } 33 | 34 | public static readonly DependencyProperty SorterProperty = DependencyProperty.RegisterAttached("Sorter", typeof(IComparer), 35 | typeof(DataGridSortBehavior)); 36 | public static readonly DependencyProperty AllowCustomSortProperty = DependencyProperty.RegisterAttached("AllowCustomSort", typeof(bool), 37 | typeof(DataGridSortBehavior), new UIPropertyMetadata(false, OnAllowCustomSortChanged)); 38 | 39 | private static void OnAllowCustomSortChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 40 | { 41 | var grid = (DataGrid)obj; 42 | 43 | bool oldAllow = (bool)e.OldValue; 44 | bool newAllow = (bool)e.NewValue; 45 | 46 | if (!oldAllow && newAllow) 47 | { 48 | grid.Sorting += HandleCustomSorting; 49 | } 50 | else 51 | { 52 | grid.Sorting -= HandleCustomSorting; 53 | } 54 | } 55 | 56 | public static bool ApplySort(DataGrid grid, DataGridColumn column) 57 | { 58 | IComparer sorter = GetSorter(column); 59 | if (sorter == null) 60 | { 61 | return false; 62 | } 63 | 64 | var listCollectionView = CollectionViewSource.GetDefaultView(grid.ItemsSource) as ListCollectionView; 65 | if (listCollectionView == null) 66 | { 67 | throw new Exception("The ICollectionView associated with the DataGrid must be of type, ListCollectionView"); 68 | } 69 | 70 | listCollectionView.CustomSort = new DataGridSortComparer(sorter, column.SortDirection ?? ListSortDirection.Ascending, column.SortMemberPath); 71 | return true; 72 | } 73 | 74 | private static void HandleCustomSorting(object sender, DataGridSortingEventArgs e) 75 | { 76 | IComparer sorter = GetSorter(e.Column); 77 | if (sorter == null) 78 | { 79 | return; 80 | } 81 | 82 | var grid = (DataGrid)sender; 83 | e.Column.SortDirection = e.Column.SortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending; 84 | if (ApplySort(grid, e.Column)) 85 | { 86 | e.Handled = true; 87 | } 88 | } 89 | 90 | private class DataGridSortComparer : IComparer 91 | { 92 | private IComparer comparer; 93 | private ListSortDirection sortDirection; 94 | private string propertyName; 95 | private PropertyInfo property; 96 | 97 | public DataGridSortComparer(IComparer comparer, ListSortDirection sortDirection, string propertyName) 98 | { 99 | this.comparer = comparer; 100 | this.sortDirection = sortDirection; 101 | this.propertyName = propertyName; 102 | } 103 | 104 | public int Compare(object x, object y) 105 | { 106 | try 107 | { 108 | PropertyInfo property = this.property ?? (this.property = x.GetType().GetProperty(propertyName)); 109 | object value1 = property.GetValue(x); 110 | object value2 = property.GetValue(y); 111 | 112 | int result = comparer.Compare(value1, value2); 113 | if (sortDirection == ListSortDirection.Descending) 114 | { 115 | result = -result; 116 | } 117 | return result; 118 | } 119 | catch (Exception e) 120 | { 121 | throw e; 122 | } 123 | 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 49 | 50 | 51 | 53 | 60 | 最快节点测试工具 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 75 | 76 | 77 | 78 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Hosts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Windows; 8 | 9 | namespace Wpf_github_hosts 10 | { 11 | public class Hosts 12 | { 13 | 14 | public static string HostsPath = @"C:\WINDOWS\system32\drivers\etc\hosts"; 15 | private static Encoding _encoding; 16 | public static void updateHosts(string data) 17 | { 18 | //通常情况下这个文件是只读的,所以写入之前要取消只读 19 | var fileList = ReadHosts(); 20 | 21 | var fileListData = fileList.FirstOrDefault(u => Regex.IsMatch(u, $" {data.Split(' ').Last()}")); 22 | if (!(fileListData is null)) 23 | fileList.Remove(fileListData); 24 | 25 | fileList.Add(data); 26 | 27 | 28 | using (var file = File.OpenWrite(HostsPath)) 29 | using (var stream = new StreamWriter(file, Encoding)) 30 | { 31 | foreach (var line in fileList) stream.WriteLine(line); 32 | } 33 | } 34 | 35 | public static List ReadHosts() 36 | { 37 | var encode = Encoding; 38 | var fileList = new List(); 39 | using (var file = File.OpenRead(HostsPath)) 40 | using (var stream = new StreamReader(file, encode)) 41 | { 42 | while (!stream.EndOfStream) 43 | { 44 | var line = stream.ReadLine(); 45 | if (!string.IsNullOrWhiteSpace(line)) 46 | fileList.Add(line); 47 | } 48 | } 49 | 50 | return fileList; 51 | } 52 | 53 | private static Encoding Encoding 54 | { 55 | get 56 | { 57 | if (_encoding is null) 58 | { 59 | try 60 | { 61 | File.SetAttributes(HostsPath, File.GetAttributes(HostsPath) & ~FileAttributes.ReadOnly); //取消只读 62 | using (var fs = new FileStream(HostsPath, FileMode.Open, FileAccess.Read)) 63 | _encoding = GetType(fs); 64 | } 65 | catch (Exception e) 66 | { 67 | MessageBox.Show("权限不足,请使用管理员权限打开"); 68 | throw; 69 | } 70 | 71 | } 72 | return _encoding; 73 | } 74 | } 75 | 76 | 77 | 78 | /// 79 | /// 通过给定的文件流,判断文件的编码类型 80 | /// 81 | /// 文件流 82 | /// 83 | /// 84 | /// 85 | /// 文件的编码类型 86 | private static Encoding GetType(FileStream fs) 87 | { 88 | byte[] Unicode = {0xFF, 0xFE, 0x41}; 89 | byte[] UnicodeBIG = {0xFE, 0xFF, 0x00}; 90 | byte[] UTF8 = {0xEF, 0xBB, 0xBF}; //带BOM 91 | var reVal = Encoding.Default; 92 | 93 | var r = new BinaryReader(fs, Encoding.Default); 94 | int i; 95 | int.TryParse(fs.Length.ToString(), out i); 96 | var ss = r.ReadBytes(i); 97 | if (IsUTF8Bytes(ss) || ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF) 98 | reVal = Encoding.UTF8; 99 | else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00) 100 | reVal = Encoding.BigEndianUnicode; 101 | else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41) reVal = Encoding.Unicode; 102 | r.Close(); 103 | return reVal; 104 | } 105 | 106 | /// 107 | /// 判断是否是不带 BOM 的 UTF8 格式 108 | /// 109 | /// 110 | /// 111 | /// 112 | /// 113 | /// 114 | private static bool IsUTF8Bytes(byte[] data) 115 | { 116 | var charByteCounter = 1; //计算当前正分析的字符应还有的字节数 117 | byte curByte; //当前分析的字节. 118 | for (var i = 0; i < data.Length; i++) 119 | { 120 | curByte = data[i]; 121 | if (charByteCounter == 1) 122 | { 123 | if (curByte >= 0x80) 124 | { 125 | //判断当前 126 | while (((curByte <<= 1) & 0x80) != 0) charByteCounter++; 127 | //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 128 | if (charByteCounter == 1 || charByteCounter > 6) return false; 129 | } 130 | } 131 | else 132 | { 133 | //若是UTF-8 此时第一位必须为1 134 | if ((curByte & 0xC0) != 0x80) return false; 135 | charByteCounter--; 136 | } 137 | } 138 | 139 | if (charByteCounter > 1) throw new Exception("非预期的byte格式"); 140 | return true; 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Wpf_github_hosts/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Wpf_github_hosts/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 89 | 90 | -------------------------------------------------------------------------------- /WPF_Best_Hosts/Lib/Hosts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Windows; 9 | using WPF_Best_Hosts.Model; 10 | 11 | namespace WPF_Best_Hosts.Lib 12 | { 13 | public static class Hosts 14 | { 15 | 16 | public static string HostsPath = @"C:\WINDOWS\system32\drivers\etc\hosts"; 17 | private static Encoding _encoding; 18 | public static ObservableCollection hostsDatas = new ObservableCollection(); 19 | public static void updateHosts(string data) 20 | { 21 | //通常情况下这个文件是只读的,所以写入之前要取消只读 22 | var fileList = ReadHosts(); 23 | 24 | var fileListData = fileList.FirstOrDefault(u => Regex.IsMatch(u, $" {data.Split(' ').Last()}")); 25 | if (!(fileListData is null)) 26 | fileList.Remove(fileListData); 27 | 28 | fileList.Add(data); 29 | 30 | 31 | using (var file = File.OpenWrite(HostsPath)) 32 | using (var stream = new StreamWriter(file, Encoding)) 33 | { 34 | foreach (var line in fileList) stream.WriteLine(line); 35 | } 36 | } 37 | 38 | public static List ReadHosts() 39 | { 40 | var encode = Encoding; 41 | var fileList = new List(); 42 | using (var file = File.OpenRead(HostsPath)) 43 | using (var stream = new StreamReader(file, encode)) 44 | { 45 | while (!stream.EndOfStream) 46 | { 47 | var line = stream.ReadLine(); 48 | if (!string.IsNullOrWhiteSpace(line)) 49 | fileList.Add(line); 50 | } 51 | } 52 | 53 | return fileList; 54 | } 55 | 56 | private static Encoding Encoding 57 | { 58 | get 59 | { 60 | if (_encoding is null) 61 | { 62 | try 63 | { 64 | File.SetAttributes(HostsPath, File.GetAttributes(HostsPath) & ~FileAttributes.ReadOnly); //取消只读 65 | using (var fs = new FileStream(HostsPath, FileMode.Open, FileAccess.Read)) 66 | _encoding = GetType(fs); 67 | } 68 | catch (Exception e) 69 | { 70 | MessageBox.Show("权限不足,请使用管理员权限打开"); 71 | throw; 72 | } 73 | 74 | } 75 | return _encoding; 76 | } 77 | } 78 | 79 | public static void InitHostsData() 80 | { 81 | var hostsLines = Hosts.ReadHosts(); 82 | hostsDatas.Clear(); 83 | foreach (var line in hostsLines) 84 | { 85 | var lineTrim = line.Trim(); 86 | if (Regex.IsMatch(lineTrim, "\\d+\\.\\d+\\.\\d+\\.\\d+[ \\t]{1,}[\\.\\w]+$")) 87 | { 88 | hostsDatas.Add(new HostsData() 89 | { 90 | Ip = Regex.Match(lineTrim, "\\d+\\.\\d+\\.\\d+\\.\\d+").Value, 91 | Domain = lineTrim.Split(' ').Last(), 92 | State = line.StartsWith("#") ? "失效" : "激活" 93 | }); 94 | } 95 | } 96 | } 97 | 98 | /// 99 | /// 通过给定的文件流,判断文件的编码类型 100 | /// 101 | /// 文件流 102 | /// 103 | /// 104 | /// 105 | /// 文件的编码类型 106 | private static Encoding GetType(FileStream fs) 107 | { 108 | byte[] Unicode = {0xFF, 0xFE, 0x41}; 109 | byte[] UnicodeBIG = {0xFE, 0xFF, 0x00}; 110 | byte[] UTF8 = {0xEF, 0xBB, 0xBF}; //带BOM 111 | var reVal = Encoding.Default; 112 | 113 | var r = new BinaryReader(fs, Encoding.Default); 114 | int i; 115 | int.TryParse(fs.Length.ToString(), out i); 116 | var ss = r.ReadBytes(i); 117 | if (IsUTF8Bytes(ss) || ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF) 118 | reVal = Encoding.UTF8; 119 | else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00) 120 | reVal = Encoding.BigEndianUnicode; 121 | else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41) reVal = Encoding.Unicode; 122 | r.Close(); 123 | return reVal; 124 | } 125 | 126 | /// 127 | /// 判断是否是不带 BOM 的 UTF8 格式 128 | /// 129 | /// 130 | /// 131 | /// 132 | /// 133 | /// 134 | private static bool IsUTF8Bytes(byte[] data) 135 | { 136 | var charByteCounter = 1; //计算当前正分析的字符应还有的字节数 137 | byte curByte; //当前分析的字节. 138 | for (var i = 0; i < data.Length; i++) 139 | { 140 | curByte = data[i]; 141 | if (charByteCounter == 1) 142 | { 143 | if (curByte >= 0x80) 144 | { 145 | //判断当前 146 | while (((curByte <<= 1) & 0x80) != 0) charByteCounter++; 147 | //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 148 | if (charByteCounter == 1 || charByteCounter > 6) return false; 149 | } 150 | } 151 | else 152 | { 153 | //若是UTF-8 此时第一位必须为1 154 | if ((curByte & 0xC0) != 0x80) return false; 155 | charByteCounter--; 156 | } 157 | } 158 | 159 | if (charByteCounter > 1) throw new Exception("非预期的byte格式"); 160 | return true; 161 | } 162 | } 163 | } -------------------------------------------------------------------------------- /WPF_Best_Hosts/View/IPTest.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |