diff --git a/PortProxyGUI/About.cs b/PortProxyGUI/About.cs index 9f52ee9..709bd99 100644 --- a/PortProxyGUI/About.cs +++ b/PortProxyGUI/About.cs @@ -1,4 +1,5 @@ -using System; +using PortProxyGUI.Utils; +using System; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; @@ -14,7 +15,7 @@ namespace PortProxyGUI PortProxyGUI = portProxyGUI; InitializeComponent(); - Font = Util.UiFont; + Font = InterfaceUtil.UiFont; label_version.Text = label_version.Text + " v" + Application.ProductVersion; } diff --git a/PortProxyGUI/Data/AppConfig.cs b/PortProxyGUI/Data/AppConfig.cs new file mode 100644 index 0000000..7beae1b --- /dev/null +++ b/PortProxyGUI/Data/AppConfig.cs @@ -0,0 +1,53 @@ +using System; +using System.Drawing; +using System.Linq; +using System.Text.RegularExpressions; + +namespace PortProxyGUI.Data +{ + public class AppConfig + { + public Size MainWindowSize = new(720, 500); + public int[] PortProxyColumnWidths = new int[] { 24, 64, 140, 100, 140, 100, 100 }; + + private readonly Regex _intArrayRegex = new(@"^\[\s*(\d+)(?:\s*,\s*(\d+))*\s*\]$"); + + public AppConfig() { } + public AppConfig(Config[] rows) + { + { + var item = rows.Where(x => x.Item == "MainWindow"); + if (int.TryParse(item.FirstOrDefault(x => x.Key == "Width")?.Value, out var width) + && int.TryParse(item.FirstOrDefault(x => x.Key == "Height")?.Value, out var height)) + { + MainWindowSize = new Size(width, height); + } + else MainWindowSize = new Size(720, 500); + } + + { + var item = rows.Where(x => x.Item == "PortProxy"); + var s_ColumnWidths = item.FirstOrDefault(x => x.Key == "ColumnWidths").Value; + var match = _intArrayRegex.Match(s_ColumnWidths); + + if (match.Success) + { + PortProxyColumnWidths = match.Groups + .OfType().Skip(1) + .SelectMany(x => x.Captures.OfType()) + .Select(x => int.Parse(x.Value)) + .ToArray(); + } + else + { +#if NETCOREAPP3_0_OR_GREATER + PortProxyColumnWidths = Array.Empty(); +#else + PortProxyColumnWidths = new int[0]; +#endif + } + } + } + + } +} diff --git a/PortProxyGUI/Data/ApplicationDbScope.cs b/PortProxyGUI/Data/ApplicationDbScope.cs index 856dd3f..99c8a0a 100644 --- a/PortProxyGUI/Data/ApplicationDbScope.cs +++ b/PortProxyGUI/Data/ApplicationDbScope.cs @@ -1,4 +1,5 @@ -using SQLib.Sqlite; +using NStandard; +using SQLib.Sqlite; using System; using System.Collections.Generic; using System.IO; @@ -8,11 +9,27 @@ namespace PortProxyGUI.Data { public class ApplicationDbScope : SqliteScope { - public static readonly string DbDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "PortProxyGUI"); - public static readonly string DbFile = Path.Combine(DbDirectory, "config.db"); - private static readonly string ConnectionString = $"Data Source={DbFile}"; + public static readonly string AppDbDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "PortProxyGUI"); + public static readonly string AppDbFile = Path.Combine(AppDbDirectory, "config.db"); - public static ApplicationDbScope UseDefault() => new ApplicationDbScope(ConnectionString); + public static ApplicationDbScope FromFile(string file) + { + var dir = Path.GetDirectoryName(file); + var fileName = Path.GetFileName(file); + + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + if (!File.Exists(fileName)) + { +#if NETCOREAPP3_0_OR_GREATER +#else + System.Data.SQLite.SQLiteConnection.CreateFile(file); +#endif + } + + var scope = new ApplicationDbScope($"Data Source=\"{file}\""); + scope.Migrate(); + return scope; + } public ApplicationDbScope(string connectionString) : base(connectionString) { @@ -20,16 +37,14 @@ namespace PortProxyGUI.Data public override void Initialize() { - if (!Directory.Exists(DbDirectory)) Directory.CreateDirectory(DbDirectory); - if (!File.Exists(DbFile)) - { -#if NET35 || NET45 - System.Data.SQLite.SQLiteConnection.CreateFile(DbFile); -#endif - } } - public void Migrate() => new ApplicationDbMigrationUtil(this).MigrateToLast(); + public void Migrate() => new MigrationUtil(this).MigrateToLast(); + + public Migration GetLastMigration() + { + return SqlQuery($"SELECT * FROM __history ORDER BY MigrationId DESC LIMIT 1;").First(); + } public IEnumerable Rules => SqlQuery($"SELECT * FROM Rules;"); @@ -79,5 +94,21 @@ namespace PortProxyGUI.Data foreach (var obj in objs) Remove(obj); } + public AppConfig GetAppConfig() + { + var configRows = SqlQuery($"SELECT * FROM Configs;"); + var appConfig = new AppConfig(configRows); + return appConfig; + } + + public void SaveAppConfig(AppConfig appConfig) + { + Sql($"UPDATE Configs SET Value = {appConfig.MainWindowSize.Width} WHERE Item = 'MainWindow' AND `Key` = 'Width';"); + Sql($"UPDATE Configs SET Value = {appConfig.MainWindowSize.Height} WHERE Item = 'MainWindow' AND `Key` = 'Height';"); + + var s_portProxyColumnWidths = $"[{appConfig.PortProxyColumnWidths.Select(x => x.ToString()).Join(", ")}]"; + Sql($"UPDATE Configs SET Value = {s_portProxyColumnWidths} WHERE Item = 'PortProxy' AND `Key` = 'ColumnWidths';"); + } + } } diff --git a/PortProxyGUI/Data/Config.cs b/PortProxyGUI/Data/Config.cs new file mode 100644 index 0000000..c8bb6d8 --- /dev/null +++ b/PortProxyGUI/Data/Config.cs @@ -0,0 +1,9 @@ +namespace PortProxyGUI.Data +{ + public class Config + { + public string Item { get; set; } + public string Key { get; set; } + public string Value { get; set; } + } +} diff --git a/PortProxyGUI/Data/ApplicationDbMigrationUtil.cs b/PortProxyGUI/Data/MigrationUtil.cs similarity index 82% rename from PortProxyGUI/Data/ApplicationDbMigrationUtil.cs rename to PortProxyGUI/Data/MigrationUtil.cs index 41c6b9a..3dec1e0 100644 --- a/PortProxyGUI/Data/ApplicationDbMigrationUtil.cs +++ b/PortProxyGUI/Data/MigrationUtil.cs @@ -7,11 +7,11 @@ using System.Windows.Forms; namespace PortProxyGUI.Data { - public class ApplicationDbMigrationUtil + public class MigrationUtil { public ApplicationDbScope DbScope { get; private set; } - public ApplicationDbMigrationUtil(ApplicationDbScope context) + public MigrationUtil(ApplicationDbScope context) { DbScope = context; EnsureHistoryTable(); @@ -29,7 +29,7 @@ namespace PortProxyGUI.Data public void EnsureUpdateVersion() { - var migration = GetLastMigration(); + var migration = DbScope.GetLastMigration(); var assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version; if (new Version(migration.ProductVersion) > assemblyVersion) @@ -47,14 +47,9 @@ Would you like to download it now?", "Upgrade", MessageBoxButtons.YesNo, Message } } - public Migration GetLastMigration() - { - return DbScope.SqlQuery($"SELECT * FROM __history ORDER BY MigrationId DESC LIMIT 1;").First(); - } - public void MigrateToLast() { - var migration = GetLastMigration(); + var migration = DbScope.GetLastMigration(); var migrationId = migration.MigrationId; var pendingMigrations = migrationId != "000000000000" ? History.SkipWhile(pair => pair.Key.MigrationId != migrationId).Skip(1) @@ -112,6 +107,21 @@ Would you like to download it now?", "Upgrade", MessageBoxButtons.YesNo, Message "INSERT INTO rules SELECT Id, Type, ListenOn, ListenPort, ConnectTo, ConnectPort, Note, `Group` FROM rulesOld;", "DROP TABLE rulesOld;", }, + + [new MigrationKey { MigrationId = "202303092024", ProductVersion = "1.4.0" }] = new[] + { + @"CREATE TABLE configs ( + Item text, + `Key` text, + Value text +);", + +"CREATE UNIQUE INDEX IX_Configs_Key ON configs ( Item, `Key` );", + +"INSERT INTO configs ( Item, `Key`, Value ) VALUES ( 'MainWindow', 'Width', '720' );", +"INSERT INTO configs ( Item, `Key`, Value ) VALUES ( 'MainWindow', 'Height', '500' );", +"INSERT INTO configs ( Item, `Key`, Value ) VALUES ( 'PortProxy', 'ColumnWidths', '[24, 64, 140, 100, 140, 100, 100]' );", + }, }; } } diff --git a/PortProxyGUI/Data/Rule.cs b/PortProxyGUI/Data/Rule.cs index a777399..9e0d491 100644 --- a/PortProxyGUI/Data/Rule.cs +++ b/PortProxyGUI/Data/Rule.cs @@ -60,5 +60,10 @@ namespace PortProxyGUI.Data if (int.TryParse(portString, out var port) && 0 < port && port < 65536) return port; else throw new NotSupportedException($"Invalid port string. ({portString})"); } + + public override bool Equals(object obj) + { + return Equals(obj as Rule); + } } } diff --git a/PortProxyGUI/Native/GenericRights.cs b/PortProxyGUI/Native/GenericRights.cs new file mode 100644 index 0000000..fdaad98 --- /dev/null +++ b/PortProxyGUI/Native/GenericRights.cs @@ -0,0 +1,10 @@ +using System; + +namespace PortProxyGUI.Native +{ + [Flags] + public enum GenericRights : uint + { + GENERIC_READ = 0x80000000, + } +} diff --git a/PortProxyGUI/Native/NativeMethods.cs b/PortProxyGUI/Native/NativeMethods.cs new file mode 100644 index 0000000..7f442f1 --- /dev/null +++ b/PortProxyGUI/Native/NativeMethods.cs @@ -0,0 +1,22 @@ +using System; +using System.Runtime.InteropServices; + +namespace PortProxyGUI.Native +{ + internal class NativeMethods + { + [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] + public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess); + + [DllImport("advapi32.dll", EntryPoint = "OpenServiceW", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceRights dwDesiredAccess); + + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ControlService(IntPtr hService, ServiceControls dwControl, ref ServiceStatus lpServiceStatus); + + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CloseServiceHandle(IntPtr hSCObject); + } +} diff --git a/PortProxyGUI/Native/ServiceControls.cs b/PortProxyGUI/Native/ServiceControls.cs new file mode 100644 index 0000000..a4b2b32 --- /dev/null +++ b/PortProxyGUI/Native/ServiceControls.cs @@ -0,0 +1,10 @@ +using System; + +namespace PortProxyGUI.Native +{ + [Flags] + public enum ServiceControls : uint + { + SERVICE_CONTROL_PARAMCHANGE = 0x00000006, + } +} diff --git a/PortProxyGUI/Native/ServiceRights.cs b/PortProxyGUI/Native/ServiceRights.cs new file mode 100644 index 0000000..104a09d --- /dev/null +++ b/PortProxyGUI/Native/ServiceRights.cs @@ -0,0 +1,10 @@ +using System; + +namespace PortProxyGUI.Native +{ + [Flags] + public enum ServiceRights : uint + { + SERVICE_PAUSE_CONTINUE = 0x0040, + } +} diff --git a/PortProxyGUI/Native/ServiceStatus.cs b/PortProxyGUI/Native/ServiceStatus.cs new file mode 100644 index 0000000..3ad590f --- /dev/null +++ b/PortProxyGUI/Native/ServiceStatus.cs @@ -0,0 +1,16 @@ +using System.Runtime.InteropServices; + +namespace PortProxyGUI.Native +{ + [StructLayout(LayoutKind.Sequential)] + public struct ServiceStatus + { + public uint dwServiceType; + public uint dwCurrentState; + public uint dwControlsAccepted; + public uint dwWin32ExitCode; + public uint dwServiceSpecificExitCode; + public uint dwCheckPoint; + public uint dwWaitHint; + } +} diff --git a/PortProxyGUI/PortProxyGUI.Designer.cs b/PortProxyGUI/PortProxyGUI.Designer.cs index 7c0962c..b405866 100644 --- a/PortProxyGUI/PortProxyGUI.Designer.cs +++ b/PortProxyGUI/PortProxyGUI.Designer.cs @@ -28,184 +28,219 @@ /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); + components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PortProxyGUI)); - this.listViewProxies = new System.Windows.Forms.ListView(); - this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); - this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); - this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); - this.columnHeader4 = new System.Windows.Forms.ColumnHeader(); - this.columnHeader5 = new System.Windows.Forms.ColumnHeader(); - this.columnHeader6 = new System.Windows.Forms.ColumnHeader(); - this.columnHeader7 = new System.Windows.Forms.ColumnHeader(); - this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); - this.toolStripMenuItem_Enable = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem_Disable = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.toolStripMenuItem_Refresh = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem_FlushDnsCache = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.toolStripMenuItem_New = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem_Modify = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem_Delete = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.toolStripMenuItem_About = new System.Windows.Forms.ToolStripMenuItem(); - this.imageListProxies = new System.Windows.Forms.ImageList(this.components); - this.contextMenuStrip1.SuspendLayout(); - this.SuspendLayout(); + listViewProxies = new System.Windows.Forms.ListView(); + columnHeader1 = new System.Windows.Forms.ColumnHeader(); + columnHeader2 = new System.Windows.Forms.ColumnHeader(); + columnHeader3 = new System.Windows.Forms.ColumnHeader(); + columnHeader4 = new System.Windows.Forms.ColumnHeader(); + columnHeader5 = new System.Windows.Forms.ColumnHeader(); + columnHeader6 = new System.Windows.Forms.ColumnHeader(); + columnHeader7 = new System.Windows.Forms.ColumnHeader(); + contextMenuStrip_RightClick = new System.Windows.Forms.ContextMenuStrip(components); + toolStripMenuItem_Enable = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem_Disable = new System.Windows.Forms.ToolStripMenuItem(); + toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + toolStripMenuItem_Refresh = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem_FlushDnsCache = new System.Windows.Forms.ToolStripMenuItem(); + toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + toolStripMenuItem_New = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem_Modify = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem_Delete = new System.Windows.Forms.ToolStripMenuItem(); + toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + toolStripMenuItem_More = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem_Import = new System.Windows.Forms.ToolStripMenuItem(); + toolStripMenuItem_Export = new System.Windows.Forms.ToolStripMenuItem(); + toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + toolStripMenuItem_About = new System.Windows.Forms.ToolStripMenuItem(); + imageListProxies = new System.Windows.Forms.ImageList(components); + saveFileDialog_Export = new System.Windows.Forms.SaveFileDialog(); + openFileDialog_Import = new System.Windows.Forms.OpenFileDialog(); + toolStripMenuItem_ResetWindowSize = new System.Windows.Forms.ToolStripMenuItem(); + toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + contextMenuStrip_RightClick.SuspendLayout(); + SuspendLayout(); // // listViewProxies // - this.listViewProxies.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.listViewProxies.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader1, - this.columnHeader2, - this.columnHeader3, - this.columnHeader4, - this.columnHeader5, - this.columnHeader6, - this.columnHeader7}); - this.listViewProxies.ContextMenuStrip = this.contextMenuStrip1; - resources.ApplyResources(this.listViewProxies, "listViewProxies"); - this.listViewProxies.FullRowSelect = true; - this.listViewProxies.HideSelection = false; - this.listViewProxies.Name = "listViewProxies"; - this.listViewProxies.SmallImageList = this.imageListProxies; - this.listViewProxies.UseCompatibleStateImageBehavior = false; - this.listViewProxies.View = System.Windows.Forms.View.Details; - this.listViewProxies.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listView1_ColumnClick); - this.listViewProxies.DoubleClick += new System.EventHandler(this.listView1_DoubleClick); - this.listViewProxies.KeyUp += new System.Windows.Forms.KeyEventHandler(this.listViewProxies_KeyUp); - this.listViewProxies.MouseUp += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseUp); + listViewProxies.BorderStyle = System.Windows.Forms.BorderStyle.None; + listViewProxies.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { columnHeader1, columnHeader2, columnHeader3, columnHeader4, columnHeader5, columnHeader6, columnHeader7 }); + listViewProxies.ContextMenuStrip = contextMenuStrip_RightClick; + resources.ApplyResources(listViewProxies, "listViewProxies"); + listViewProxies.FullRowSelect = true; + listViewProxies.HideSelection = false; + listViewProxies.Name = "listViewProxies"; + listViewProxies.SmallImageList = imageListProxies; + listViewProxies.UseCompatibleStateImageBehavior = false; + listViewProxies.View = System.Windows.Forms.View.Details; + listViewProxies.ColumnClick += listView1_ColumnClick; + listViewProxies.ColumnWidthChanged += listViewProxies_ColumnWidthChanged; + listViewProxies.DoubleClick += listView1_DoubleClick; + listViewProxies.KeyUp += listViewProxies_KeyUp; + listViewProxies.MouseUp += listView1_MouseUp; // // columnHeader1 // - resources.ApplyResources(this.columnHeader1, "columnHeader1"); + resources.ApplyResources(columnHeader1, "columnHeader1"); // // columnHeader2 // - resources.ApplyResources(this.columnHeader2, "columnHeader2"); + resources.ApplyResources(columnHeader2, "columnHeader2"); // // columnHeader3 // - resources.ApplyResources(this.columnHeader3, "columnHeader3"); + resources.ApplyResources(columnHeader3, "columnHeader3"); // // columnHeader4 // - this.columnHeader4.Tag = ""; - resources.ApplyResources(this.columnHeader4, "columnHeader4"); + columnHeader4.Tag = ""; + resources.ApplyResources(columnHeader4, "columnHeader4"); // // columnHeader5 // - resources.ApplyResources(this.columnHeader5, "columnHeader5"); + resources.ApplyResources(columnHeader5, "columnHeader5"); // // columnHeader6 // - this.columnHeader6.Tag = ""; - resources.ApplyResources(this.columnHeader6, "columnHeader6"); + columnHeader6.Tag = ""; + resources.ApplyResources(columnHeader6, "columnHeader6"); // // columnHeader7 // - resources.ApplyResources(this.columnHeader7, "columnHeader7"); + resources.ApplyResources(columnHeader7, "columnHeader7"); // - // contextMenuStrip1 + // contextMenuStrip_RightClick // - this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripMenuItem_Enable, - this.toolStripMenuItem_Disable, - this.toolStripSeparator3, - this.toolStripMenuItem_Refresh, - this.toolStripMenuItem_FlushDnsCache, - this.toolStripSeparator2, - this.toolStripMenuItem_New, - this.toolStripMenuItem_Modify, - this.toolStripMenuItem_Delete, - this.toolStripSeparator1, - this.toolStripMenuItem_About}); - this.contextMenuStrip1.Name = "contextMenuStrip1"; - resources.ApplyResources(this.contextMenuStrip1, "contextMenuStrip1"); - this.contextMenuStrip1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.contextMenuStrip1_MouseClick); + contextMenuStrip_RightClick.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolStripMenuItem_Enable, toolStripMenuItem_Disable, toolStripSeparator3, toolStripMenuItem_Refresh, toolStripMenuItem_FlushDnsCache, toolStripSeparator2, toolStripMenuItem_New, toolStripMenuItem_Modify, toolStripMenuItem_Delete, toolStripSeparator1, toolStripMenuItem_More, toolStripSeparator4, toolStripMenuItem_About }); + contextMenuStrip_RightClick.Name = "contextMenuStrip1"; + resources.ApplyResources(contextMenuStrip_RightClick, "contextMenuStrip_RightClick"); + contextMenuStrip_RightClick.MouseClick += contextMenuStrip_RightClick_MouseClick; // // toolStripMenuItem_Enable // - this.toolStripMenuItem_Enable.Name = "toolStripMenuItem_Enable"; - resources.ApplyResources(this.toolStripMenuItem_Enable, "toolStripMenuItem_Enable"); + toolStripMenuItem_Enable.Name = "toolStripMenuItem_Enable"; + resources.ApplyResources(toolStripMenuItem_Enable, "toolStripMenuItem_Enable"); // // toolStripMenuItem_Disable // - this.toolStripMenuItem_Disable.Name = "toolStripMenuItem_Disable"; - resources.ApplyResources(this.toolStripMenuItem_Disable, "toolStripMenuItem_Disable"); + toolStripMenuItem_Disable.Name = "toolStripMenuItem_Disable"; + resources.ApplyResources(toolStripMenuItem_Disable, "toolStripMenuItem_Disable"); // // toolStripSeparator3 // - this.toolStripSeparator3.Name = "toolStripSeparator3"; - resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3"); + toolStripSeparator3.Name = "toolStripSeparator3"; + resources.ApplyResources(toolStripSeparator3, "toolStripSeparator3"); // // toolStripMenuItem_Refresh // - this.toolStripMenuItem_Refresh.Name = "toolStripMenuItem_Refresh"; - resources.ApplyResources(this.toolStripMenuItem_Refresh, "toolStripMenuItem_Refresh"); + toolStripMenuItem_Refresh.Name = "toolStripMenuItem_Refresh"; + resources.ApplyResources(toolStripMenuItem_Refresh, "toolStripMenuItem_Refresh"); // // toolStripMenuItem_FlushDnsCache // - this.toolStripMenuItem_FlushDnsCache.Name = "toolStripMenuItem_FlushDnsCache"; - resources.ApplyResources(this.toolStripMenuItem_FlushDnsCache, "toolStripMenuItem_FlushDnsCache"); + toolStripMenuItem_FlushDnsCache.Name = "toolStripMenuItem_FlushDnsCache"; + resources.ApplyResources(toolStripMenuItem_FlushDnsCache, "toolStripMenuItem_FlushDnsCache"); // // toolStripSeparator2 // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - resources.ApplyResources(this.toolStripSeparator2, "toolStripSeparator2"); + toolStripSeparator2.Name = "toolStripSeparator2"; + resources.ApplyResources(toolStripSeparator2, "toolStripSeparator2"); // // toolStripMenuItem_New // - this.toolStripMenuItem_New.Name = "toolStripMenuItem_New"; - resources.ApplyResources(this.toolStripMenuItem_New, "toolStripMenuItem_New"); + toolStripMenuItem_New.Name = "toolStripMenuItem_New"; + resources.ApplyResources(toolStripMenuItem_New, "toolStripMenuItem_New"); // // toolStripMenuItem_Modify // - this.toolStripMenuItem_Modify.Name = "toolStripMenuItem_Modify"; - resources.ApplyResources(this.toolStripMenuItem_Modify, "toolStripMenuItem_Modify"); + toolStripMenuItem_Modify.Name = "toolStripMenuItem_Modify"; + resources.ApplyResources(toolStripMenuItem_Modify, "toolStripMenuItem_Modify"); // // toolStripMenuItem_Delete // - this.toolStripMenuItem_Delete.Name = "toolStripMenuItem_Delete"; - resources.ApplyResources(this.toolStripMenuItem_Delete, "toolStripMenuItem_Delete"); + toolStripMenuItem_Delete.Name = "toolStripMenuItem_Delete"; + resources.ApplyResources(toolStripMenuItem_Delete, "toolStripMenuItem_Delete"); // // toolStripSeparator1 // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1"); + toolStripSeparator1.Name = "toolStripSeparator1"; + resources.ApplyResources(toolStripSeparator1, "toolStripSeparator1"); + // + // toolStripMenuItem_More + // + toolStripMenuItem_More.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { toolStripMenuItem_Import, toolStripMenuItem_Export, toolStripSeparator5, toolStripMenuItem_ResetWindowSize }); + toolStripMenuItem_More.Name = "toolStripMenuItem_More"; + resources.ApplyResources(toolStripMenuItem_More, "toolStripMenuItem_More"); + // + // toolStripMenuItem_Import + // + toolStripMenuItem_Import.Name = "toolStripMenuItem_Import"; + resources.ApplyResources(toolStripMenuItem_Import, "toolStripMenuItem_Import"); + toolStripMenuItem_Import.Click += toolStripMenuItem_Import_Click; + // + // toolStripMenuItem_Export + // + toolStripMenuItem_Export.Name = "toolStripMenuItem_Export"; + resources.ApplyResources(toolStripMenuItem_Export, "toolStripMenuItem_Export"); + toolStripMenuItem_Export.Click += toolStripMenuItem_Export_Click; + // + // toolStripSeparator4 + // + toolStripSeparator4.Name = "toolStripSeparator4"; + resources.ApplyResources(toolStripSeparator4, "toolStripSeparator4"); // // toolStripMenuItem_About // - this.toolStripMenuItem_About.Name = "toolStripMenuItem_About"; - resources.ApplyResources(this.toolStripMenuItem_About, "toolStripMenuItem_About"); + toolStripMenuItem_About.Name = "toolStripMenuItem_About"; + resources.ApplyResources(toolStripMenuItem_About, "toolStripMenuItem_About"); // // imageListProxies // - this.imageListProxies.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit; - this.imageListProxies.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListProxies.ImageStream"))); - this.imageListProxies.TransparentColor = System.Drawing.Color.Transparent; - this.imageListProxies.Images.SetKeyName(0, "disable.png"); - this.imageListProxies.Images.SetKeyName(1, "enable.png"); + imageListProxies.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit; + imageListProxies.ImageStream = (System.Windows.Forms.ImageListStreamer)resources.GetObject("imageListProxies.ImageStream"); + imageListProxies.TransparentColor = System.Drawing.Color.Transparent; + imageListProxies.Images.SetKeyName(0, "disable.png"); + imageListProxies.Images.SetKeyName(1, "enable.png"); + // + // saveFileDialog_Export + // + resources.ApplyResources(saveFileDialog_Export, "saveFileDialog_Export"); + // + // openFileDialog_Import + // + openFileDialog_Import.FileName = "openFileDialog1"; + resources.ApplyResources(openFileDialog_Import, "openFileDialog_Import"); + // + // toolStripMenuItem_ResetWindowSize + // + toolStripMenuItem_ResetWindowSize.Name = "toolStripMenuItem_ResetWindowSize"; + resources.ApplyResources(toolStripMenuItem_ResetWindowSize, "toolStripMenuItem_ResetWindowSize"); + toolStripMenuItem_ResetWindowSize.Click += toolStripMenuItem_ResetWindowSize_Click; + // + // toolStripSeparator5 + // + toolStripSeparator5.Name = "toolStripSeparator5"; + resources.ApplyResources(toolStripSeparator5, "toolStripSeparator5"); // // PortProxyGUI // resources.ApplyResources(this, "$this"); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.listViewProxies); - this.Name = "PortProxyGUI"; - this.Load += new System.EventHandler(this.PortProxyGUI_Load); - this.Shown += new System.EventHandler(this.PortProxyGUI_Shown); - this.contextMenuStrip1.ResumeLayout(false); - this.ResumeLayout(false); - + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + Controls.Add(listViewProxies); + Name = "PortProxyGUI"; + FormClosing += PortProxyGUI_FormClosing; + Load += PortProxyGUI_Load; + Shown += PortProxyGUI_Shown; + Resize += PortProxyGUI_Resize; + contextMenuStrip_RightClick.ResumeLayout(false); + ResumeLayout(false); } #endregion private System.Windows.Forms.ColumnHeader columnHeader2; private System.Windows.Forms.ColumnHeader columnHeader3; - private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip_RightClick; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_New; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_Delete; private System.Windows.Forms.ColumnHeader columnHeader4; @@ -224,6 +259,14 @@ private System.Windows.Forms.ColumnHeader columnHeader7; internal System.Windows.Forms.ListView listViewProxies; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_FlushDnsCache; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_More; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_Export; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_Import; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.SaveFileDialog saveFileDialog_Export; + private System.Windows.Forms.OpenFileDialog openFileDialog_Import; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_ResetWindowSize; } } diff --git a/PortProxyGUI/PortProxyGUI.cs b/PortProxyGUI/PortProxyGUI.cs index f894cac..d7a5e6a 100644 --- a/PortProxyGUI/PortProxyGUI.cs +++ b/PortProxyGUI/PortProxyGUI.cs @@ -1,6 +1,11 @@ using NStandard; +using PortProxyGUI.Data; +using PortProxyGUI.UI; +using PortProxyGUI.Utils; using System; using System.Data; +using System.Drawing; +using System.IO; using System.Linq; using System.Windows.Forms; using static System.Windows.Forms.ListViewItem; @@ -9,21 +14,29 @@ namespace PortProxyGUI { public partial class PortProxyGUI : Form { + private readonly ListViewColumnSorter lvwColumnSorter = new ListViewColumnSorter(); + public SetProxy SetProxyForm; public About AboutForm; - private ListViewColumnSorter lvwColumnSorter; + private AppConfig AppConfig; public PortProxyGUI() { InitializeComponent(); - Font = Util.UiFont; + Font = InterfaceUtil.UiFont; - lvwColumnSorter = new ListViewColumnSorter(); listViewProxies.ListViewItemSorter = lvwColumnSorter; } private void PortProxyGUI_Load(object sender, EventArgs e) { + AppConfig = Program.Database.GetAppConfig(); + + var size = AppConfig.MainWindowSize; + Left -= (size.Width - Width) / 2; + Top -= (size.Height - Height) / 2; + + ResetWindowSize(); } private void PortProxyGUI_Shown(object sender, EventArgs e) @@ -31,6 +44,21 @@ namespace PortProxyGUI RefreshProxyList(); } + private void ResetWindowSize() + { + Size = AppConfig.MainWindowSize; + + if (AppConfig.PortProxyColumnWidths.Length != listViewProxies.Columns.Count) + { + Any.ReDim(ref AppConfig.PortProxyColumnWidths, listViewProxies.Columns.Count); + } + + foreach (var (column, configWidth) in Any.Zip(listViewProxies.Columns.OfType(), AppConfig.PortProxyColumnWidths)) + { + column.Width = configWidth; + } + } + private Data.Rule ParseRule(ListViewItem item) { var subItems = item.SubItems.OfType().ToArray(); @@ -62,7 +90,7 @@ namespace PortProxyGUI try { var rule = ParseRule(item); - PortProxyUtil.AddOrUpdateProxy(rule); + PortPorxyUtil.AddOrUpdateProxy(rule); } catch (NotSupportedException ex) { @@ -70,6 +98,7 @@ namespace PortProxyGUI return; } } + PortPorxyUtil.ParamChange(); } private void DisableSelectedProxies() @@ -82,7 +111,7 @@ namespace PortProxyGUI try { var rule = ParseRule(item); - PortProxyUtil.DeleteProxy(rule); + PortPorxyUtil.DeleteProxy(rule); } catch (NotSupportedException ex) { @@ -90,13 +119,14 @@ namespace PortProxyGUI return; } } + PortPorxyUtil.ParamChange(); } private void DeleteSelectedProxies() { var items = listViewProxies.SelectedItems.OfType(); DisableSelectedProxies(); - Program.SqliteDbScope.RemoveRange(items.Select(x => new Data.Rule { Id = x.Tag.ToString() })); + Program.Database.RemoveRange(items.Select(x => new Data.Rule { Id = x.Tag.ToString() })); foreach (var item in items) listViewProxies.Items.Remove(item); } @@ -172,8 +202,8 @@ namespace PortProxyGUI public void RefreshProxyList() { - var proxies = PortProxyUtil.GetProxies(); - var rules = Program.SqliteDbScope.Rules.ToArray(); + var proxies = PortPorxyUtil.GetProxies(); + var rules = Program.Database.Rules.ToArray(); foreach (var proxy in proxies) { var matchedRule = rules.FirstOrDefault(r => r.EqualsWithKeys(proxy)); @@ -188,33 +218,19 @@ namespace PortProxyGUI where proxy.Valid && proxy.Id is not null select proxy; - Program.SqliteDbScope.AddRange(pendingAdds); - Program.SqliteDbScope.UpdateRange(pendingUpdates); + Program.Database.AddRange(pendingAdds); + Program.Database.UpdateRange(pendingUpdates); - rules = Program.SqliteDbScope.Rules.ToArray(); + rules = Program.Database.Rules.ToArray(); InitProxyGroups(rules); InitProxyItems(rules, proxies); } - public void FlushDnsCache() + private void contextMenuStrip_RightClick_MouseClick(object sender, MouseEventArgs e) { - try + if (sender is ContextMenuStrip strip) { - CmdUtil.FlushDNSCache(); - RefreshProxyList(); - } - catch (NotSupportedException ex) - { - MessageBox.Show(ex.Message, "Exclamation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); - return; - } - } - - private void contextMenuStrip1_MouseClick(object sender, MouseEventArgs e) - { - if (sender is ContextMenuStrip _sender) - { - var selected = _sender.Items.OfType().Where(x => x.Selected).FirstOrDefault(); + var selected = strip.Items.OfType().Where(x => x.Selected).FirstOrDefault(); if (selected is null || !selected.Enabled) return; switch (selected) @@ -238,7 +254,7 @@ namespace PortProxyGUI RefreshProxyList(); break; case ToolStripMenuItem item when item == toolStripMenuItem_FlushDnsCache: - FlushDnsCache(); + DnsUtil.FlushCache(); break; case ToolStripMenuItem item when item == toolStripMenuItem_Delete: DeleteSelectedProxies(); break; @@ -257,21 +273,21 @@ namespace PortProxyGUI private void listView1_MouseUp(object sender, MouseEventArgs e) { - if (sender is ListView _sender) + if (sender is ListView listView) { - toolStripMenuItem_Enable.Enabled = e.Button == MouseButtons.Right && _sender.SelectedItems.OfType().Any(x => x.ImageIndex == 0); - toolStripMenuItem_Disable.Enabled = e.Button == MouseButtons.Right && _sender.SelectedItems.OfType().Any(x => x.ImageIndex == 1); + toolStripMenuItem_Enable.Enabled = e.Button == MouseButtons.Right && listView.SelectedItems.OfType().Any(x => x.ImageIndex == 0); + toolStripMenuItem_Disable.Enabled = e.Button == MouseButtons.Right && listView.SelectedItems.OfType().Any(x => x.ImageIndex == 1); - toolStripMenuItem_Delete.Enabled = e.Button == MouseButtons.Right && _sender.SelectedItems.OfType().Any(); - toolStripMenuItem_Modify.Enabled = e.Button == MouseButtons.Right && _sender.SelectedItems.OfType().Count() == 1; + toolStripMenuItem_Delete.Enabled = e.Button == MouseButtons.Right && listView.SelectedItems.OfType().Any(); + toolStripMenuItem_Modify.Enabled = e.Button == MouseButtons.Right && listView.SelectedItems.OfType().Count() == 1; } } private void listView1_DoubleClick(object sender, EventArgs e) { - if (sender is ListView _sender) + if (sender is ListView listView) { - var selectAny = _sender.SelectedItems.OfType().Any(); + var selectAny = listView.SelectedItems.OfType().Any(); if (selectAny) { if (SetProxyForm == null) SetProxyForm = new SetProxy(this); @@ -314,5 +330,69 @@ namespace PortProxyGUI if (e.KeyCode == Keys.Delete) DeleteSelectedProxies(); } } + + private void listViewProxies_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e) + { + if (AppConfig is not null && sender is ListView listView) + { + AppConfig.PortProxyColumnWidths[e.ColumnIndex] = listView.Columns[e.ColumnIndex].Width; + } + } + + private void PortProxyGUI_FormClosing(object sender, FormClosingEventArgs e) + { + Program.Database.SaveAppConfig(AppConfig); + } + + private void PortProxyGUI_Resize(object sender, EventArgs e) + { + if (AppConfig is not null && sender is Form form) + { + AppConfig.MainWindowSize = form.Size; + } + } + + private void toolStripMenuItem_Export_Click(object sender, EventArgs e) + { + using var dialog = saveFileDialog_Export; + + var result = dialog.ShowDialog(); + if (result == DialogResult.OK) + { + var fileName = dialog.FileName; + File.Copy(ApplicationDbScope.AppDbFile, fileName, true); + } + } + + private void toolStripMenuItem_Import_Click(object sender, EventArgs e) + { + using var dialog = openFileDialog_Import; + + var result = dialog.ShowDialog(); + if (result == DialogResult.OK) + { + var fileName = dialog.FileName; + using (var scope = ApplicationDbScope.FromFile(fileName)) + { + foreach (var rule in scope.Rules) + { + var exsist = Program.Database.GetRule(rule.Type, rule.ListenOn, rule.ListenPort); + if (exsist is null) + { + rule.Id = Guid.NewGuid().ToString(); + Program.Database.Add(rule); + } + } + } + + RefreshProxyList(); + } + } + + private void toolStripMenuItem_ResetWindowSize_Click(object sender, EventArgs e) + { + AppConfig = new AppConfig(); + ResetWindowSize(); + } } } diff --git a/PortProxyGUI/PortProxyGUI.csproj b/PortProxyGUI/PortProxyGUI.csproj index 5147f69..915d212 100644 --- a/PortProxyGUI/PortProxyGUI.csproj +++ b/PortProxyGUI/PortProxyGUI.csproj @@ -14,7 +14,7 @@ portproxy TCP/IP redirector LICENSE.md Copyright © nstandard.net 2020 - 1.3.2 + 1.4.0 icon.ico Microsoft Sans Serif, 8pt PPGUI @@ -39,7 +39,7 @@ - + diff --git a/PortProxyGUI/PortProxyGUI.resx b/PortProxyGUI/PortProxyGUI.resx index 55babf0..822a02e 100644 --- a/PortProxyGUI/PortProxyGUI.resx +++ b/PortProxyGUI/PortProxyGUI.resx @@ -1,4 +1,64 @@ - + + + @@ -52,10 +112,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -98,82 +158,112 @@ Comment - 104 + 100 - - 17, 17 - + + 17, 17 + - 180, 22 + 174, 22 Enable (&E) - 180, 22 + 174, 22 Disable (&I) - 177, 6 + 171, 6 - 180, 22 + 174, 22 Refresh (&F) - 180, 22 + 174, 22 Flush DNS Cache - Will perform ipconfig/flushDNS + Perform ipconfig /flushDNS - 177, 6 + 171, 6 - 180, 22 + 174, 22 New (&N) ... - 180, 22 + 174, 22 Modify (&M) ... - 180, 22 + 174, 22 Delete (&D) - 177, 6 + 171, 6 + + + 186, 22 + + + Import + + + 186, 22 + + + Export + + + 183, 6 + + + 186, 22 + + + Reset Window + + + 174, 22 + + + More + + + 171, 6 - 180, 22 + 174, 22 About - - 181, 220 + + 175, 226 - - contextMenuStrip1 + + contextMenuStrip_RightClick - + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Fill @@ -187,54 +277,54 @@ 4, 3, 4, 3 - 704, 456 + 704, 461 + + + 239, 17 - - 182, 17 - - AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs - LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu - SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA3AgAAAJNU0Z0AUkBTAIBAQIB - AAEwAQEBMAEBARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMAAUADAAEQAwABAQEAAQgG - AAEEGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEAAfABygGmAQABMwUAATMB - AAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEAAYABfAH/AQACUAH/AQAB - kwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFmAwABmQMAAcwCAAEzAwAC - MwIAATMBZgIAATMBmQIAATMBzAIAATMB/wIAAWYDAAFmATMCAAJmAgABZgGZAgABZgHMAgABZgH/AgAB - mQMAAZkBMwIAAZkBZgIAApkCAAGZAcwCAAGZAf8CAAHMAwABzAEzAgABzAFmAgABzAGZAgACzAIAAcwB - /wIAAf8BZgIAAf8BmQIAAf8BzAEAATMB/wIAAf8BAAEzAQABMwEAAWYBAAEzAQABmQEAATMBAAHMAQAB - MwEAAf8BAAH/ATMCAAMzAQACMwFmAQACMwGZAQACMwHMAQACMwH/AQABMwFmAgABMwFmATMBAAEzAmYB - AAEzAWYBmQEAATMBZgHMAQABMwFmAf8BAAEzAZkCAAEzAZkBMwEAATMBmQFmAQABMwKZAQABMwGZAcwB - AAEzAZkB/wEAATMBzAIAATMBzAEzAQABMwHMAWYBAAEzAcwBmQEAATMCzAEAATMBzAH/AQABMwH/ATMB - AAEzAf8BZgEAATMB/wGZAQABMwH/AcwBAAEzAv8BAAFmAwABZgEAATMBAAFmAQABZgEAAWYBAAGZAQAB - ZgEAAcwBAAFmAQAB/wEAAWYBMwIAAWYCMwEAAWYBMwFmAQABZgEzAZkBAAFmATMBzAEAAWYBMwH/AQAC - ZgIAAmYBMwEAA2YBAAJmAZkBAAJmAcwBAAFmAZkCAAFmAZkBMwEAAWYBmQFmAQABZgKZAQABZgGZAcwB - AAFmAZkB/wEAAWYBzAIAAWYBzAEzAQABZgHMAZkBAAFmAswBAAFmAcwB/wEAAWYB/wIAAWYB/wEzAQAB - ZgH/AZkBAAFmAf8BzAEAAcwBAAH/AQAB/wEAAcwBAAKZAgABmQEzAZkBAAGZAQABmQEAAZkBAAHMAQAB - mQMAAZkCMwEAAZkBAAFmAQABmQEzAcwBAAGZAQAB/wEAAZkBZgIAAZkBZgEzAQABmQEzAWYBAAGZAWYB - mQEAAZkBZgHMAQABmQEzAf8BAAKZATMBAAKZAWYBAAOZAQACmQHMAQACmQH/AQABmQHMAgABmQHMATMB - AAFmAcwBZgEAAZkBzAGZAQABmQLMAQABmQHMAf8BAAGZAf8CAAGZAf8BMwEAAZkBzAFmAQABmQH/AZkB - AAGZAf8BzAEAAZkC/wEAAcwDAAGZAQABMwEAAcwBAAFmAQABzAEAAZkBAAHMAQABzAEAAZkBMwIAAcwC - MwEAAcwBMwFmAQABzAEzAZkBAAHMATMBzAEAAcwBMwH/AQABzAFmAgABzAFmATMBAAGZAmYBAAHMAWYB - mQEAAcwBZgHMAQABmQFmAf8BAAHMAZkCAAHMAZkBMwEAAcwBmQFmAQABzAKZAQABzAGZAcwBAAHMAZkB - /wEAAswCAALMATMBAALMAWYBAALMAZkBAAPMAQACzAH/AQABzAH/AgABzAH/ATMBAAGZAf8BZgEAAcwB - /wGZAQABzAH/AcwBAAHMAv8BAAHMAQABMwEAAf8BAAFmAQAB/wEAAZkBAAHMATMCAAH/AjMBAAH/ATMB - ZgEAAf8BMwGZAQAB/wEzAcwBAAH/ATMB/wEAAf8BZgIAAf8BZgEzAQABzAJmAQAB/wFmAZkBAAH/AWYB - zAEAAcwBZgH/AQAB/wGZAgAB/wGZATMBAAH/AZkBZgEAAf8CmQEAAf8BmQHMAQAB/wGZAf8BAAH/AcwC - AAH/AcwBMwEAAf8BzAFmAQAB/wHMAZkBAAH/AswBAAH/AcwB/wEAAv8BMwEAAcwB/wFmAQAC/wGZAQAC - /wHMAQACZgH/AQABZgH/AWYBAAFmAv8BAAH/AmYBAAH/AWYB/wEAAv8BZgEAASEBAAGlAQADXwEAA3cB - AAOGAQADlgEAA8sBAAOyAQAD1wEAA90BAAPjAQAD6gEAA/EBAAP4AQAB8AH7Af8BAAGkAqABAAOAAwAB - /wIAAf8DAAL/AQAB/wMAAf8BAAH/AQAC/wIAA/8EAAr0NAAB/wGUChcBlAH/AgAB/wG6CpUBugH/IgAB - lAwXAZQCAAG6DJUBuiIADhcCAA6VIgAEFwEWAfQC/wH0ARYEFwIADpUiAAMXARYB/wG9ARYBlAH0Af8B - FgMXAgAFlQK7B5UiAAMXAfQBvQIXAZQB/wL0AxcCAASVAboC/wHBBpUiAAMXAf8BFgEXAZQB/wKUAf8D - FwIAA5UBugH/AcEBugH/AcEFlSIAAxcB/wKUAf8BlAEXARYB/wMXAgADlQH/AcEClQG6Af8BwQSVIgAD - FwL0Af8BlAIXAb0B9AMXAgAIlQG6Af8BwQOVIgADFwEWAf8B9AGUARYBvQH/ARYDFwIACZUBugH/A5Ui - AAQXARYB9AL/AfQBFgQXAf8BAA6VAf8hAA4XAf8BAA6VAf8hAAGUDBcBlAIAAboMlQG6IgAB/wGUChcB - lAH/AgAB/wG6CpUBugH/NAAB/wj0JAABQgFNAT4HAAE+AwABKAMAAUADAAEQAwABAQEAAQEFAAGAFwAD - /wEAAeABBwL/BAABgAEBAYABAQQAAYABAQGAAQEEAAGAAQEBgAEBBAABgAEBAYABAQQAAYABAQGAAQEE - AAGAAQEBgAEBBAABgAEBAYABAQQAAYABAQGAAQEEAAGAAQEBgAEBBAABgAEBAYABAQQAAYABAAGABQAB - gAEAAYAFAAGAAQEBgAEBBAABgAEBAYABAQQAAv8B4AEPBAAL + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADc + CAAAAk1TRnQBSQFMAgEBAgEAAYwBAQGQAQEBEAEAARABAAT/AQkBEAj/AUIBTQE2AQQGAAE2AQQCAAEo + AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA + AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 + AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA + AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm + AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM + AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA + ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz + AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ + AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM + AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA + AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA + AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ + AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ + AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA + AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm + ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ + Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz + AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA + AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM + AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM + ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM + Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA + AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM + AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ + AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz + AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm + AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw + AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/wQACvQ0AAH/AZQKFwGU + Af8CAAH/AboKlQG6Af8iAAGUDBcBlAIAAboMlQG6IgAOFwIADpUiAAQXARYB9AL/AfQBFgQXAgAOlSIA + AxcBFgH/Ab0BFgGUAfQB/wEWAxcCAAWVArsHlSIAAxcB9AG9AhcBlAH/AvQDFwIABJUBugL/AcEGlSIA + AxcB/wEWARcBlAH/ApQB/wMXAgADlQG6Af8BwQG6Af8BwQWVIgADFwH/ApQB/wGUARcBFgH/AxcCAAOV + Af8BwQKVAboB/wHBBJUiAAMXAvQB/wGUAhcBvQH0AxcCAAiVAboB/wHBA5UiAAMXARYB/wH0AZQBFgG9 + Af8BFgMXAgAJlQG6Af8DlSIABBcBFgH0Av8B9AEWBBcB/wEADpUB/yEADhcB/wEADpUB/yEAAZQMFwGU + AgABugyVAboiAAH/AZQKFwGUAf8CAAH/AboKlQG6Af80AAH/CPQkAAFCAU0BPgcAAT4DAAEoAwABQAMA + ARADAAEBAQABAQUAAYAXAAP/AQAB4AEHAv8EAAGAAQEBgAEBBAABgAEBAYABAQQAAYABAQGAAQEEAAGA + AQEBgAEBBAABgAEBAYABAQQAAYABAQGAAQEEAAGAAQEBgAEBBAABgAEBAYABAQQAAYABAQGAAQEEAAGA + AQEBgAEBBAABgAEAAYAFAAGAAQABgAUAAYABAQGAAQEEAAGAAQEBgAEBBAAC/wHgAQ8aAAs= @@ -252,14 +342,26 @@ 1 - + + 389, 17 + + + Database File|*.db + + + 569, 17 + + + Database File|*.db + + True - + 6, 13 - 704, 456 + 704, 461 @@ -2530,6 +2632,30 @@ System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + toolStripMenuItem_More + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripMenuItem_Import + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripMenuItem_Export + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator4 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + toolStripMenuItem_About @@ -2542,6 +2668,30 @@ System.Windows.Forms.ImageList, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + saveFileDialog_Export + + + System.Windows.Forms.SaveFileDialog, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + openFileDialog_Import + + + System.Windows.Forms.OpenFileDialog, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripMenuItem_ResetWindowSize + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripSeparator5 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + PortProxyGUI diff --git a/PortProxyGUI/PortProxyGUI.zh-CN.resx b/PortProxyGUI/PortProxyGUI.zh-CN.resx index 6bc18b9..e001a81 100644 --- a/PortProxyGUI/PortProxyGUI.zh-CN.resx +++ b/PortProxyGUI/PortProxyGUI.zh-CN.resx @@ -112,15 +112,15 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 24 @@ -160,7 +160,7 @@ 104 - + 17, 17 @@ -173,7 +173,7 @@ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Fill @@ -194,10 +194,10 @@ - AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADc - CAAAAk1TRnQBSQFMAgEBAgEAASABAQEkAQEBEAEAARABAAT/AQkBEAj/AUIBTQE2AQQGAAE2AQQCAAEo + CAAAAk1TRnQBSQFMAgEBAgEAASABAQEwAQEBEAEAARABAAT/AQkBEAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -2593,4 +2593,22 @@ System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 清理 DNS 缓存 + + + 执行 ipconfig /flushDNS + + + 导出 + + + 导入 + + + 更多 + + + 重置窗口 + \ No newline at end of file diff --git a/PortProxyGUI/Program.cs b/PortProxyGUI/Program.cs index 0670b84..7fa50be 100644 --- a/PortProxyGUI/Program.cs +++ b/PortProxyGUI/Program.cs @@ -1,12 +1,15 @@ using PortProxyGUI.Data; using System; +using System.Globalization; +using System.IO; +using System.Threading; using System.Windows.Forms; namespace PortProxyGUI { static class Program { - public static readonly ApplicationDbScope SqliteDbScope = ApplicationDbScope.UseDefault(); + public static readonly ApplicationDbScope Database = ApplicationDbScope.FromFile(ApplicationDbScope.AppDbFile); /// /// The main entry point for the application. @@ -14,8 +17,6 @@ namespace PortProxyGUI [STAThread] static void Main() { - SqliteDbScope.Migrate(); - // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. #if NET6_0_OR_GREATER diff --git a/PortProxyGUI/SetProxy.cs b/PortProxyGUI/SetProxy.cs index 1020ae2..ff9dfcf 100644 --- a/PortProxyGUI/SetProxy.cs +++ b/PortProxyGUI/SetProxy.cs @@ -1,5 +1,6 @@ using NStandard; using PortProxyGUI.Data; +using PortProxyGUI.Utils; using System; using System.Drawing; using System.Linq; @@ -22,7 +23,7 @@ namespace PortProxyGUI ParentWindow = parent; InitializeComponent(); - Font = Util.UiFont; + Font = InterfaceUtil.UiFont; AutoTypeString = comboBox_Type.Text = comboBox_Type.Items.OfType().First(); var groupNames = ( @@ -115,22 +116,23 @@ namespace PortProxyGUI if (_updateMode) { - var oldRule = Program.SqliteDbScope.GetRule(_itemRule.Type, _itemRule.ListenOn, _itemRule.ListenPort); - PortProxyUtil.DeleteProxy(oldRule); - Program.SqliteDbScope.Remove(oldRule); + var oldRule = Program.Database.GetRule(_itemRule.Type, _itemRule.ListenOn, _itemRule.ListenPort); + PortPorxyUtil.DeleteProxy(oldRule); + Program.Database.Remove(oldRule); - PortProxyUtil.AddOrUpdateProxy(rule); - Program.SqliteDbScope.Add(rule); + PortPorxyUtil.AddOrUpdateProxy(rule); + Program.Database.Add(rule); ParentWindow.UpdateListViewItem(_listViewItem, rule, 1); } else { - PortProxyUtil.AddOrUpdateProxy(rule); - Program.SqliteDbScope.Add(rule); + PortPorxyUtil.AddOrUpdateProxy(rule); + Program.Database.Add(rule); ParentWindow.RefreshProxyList(); } + PortPorxyUtil.ParamChange(); Close(); } diff --git a/PortProxyGUI/~DS/ListViewColumnSorter.cs b/PortProxyGUI/UI/ListViewColumnSorter.cs similarity index 98% rename from PortProxyGUI/~DS/ListViewColumnSorter.cs rename to PortProxyGUI/UI/ListViewColumnSorter.cs index b7b7610..2167af1 100644 --- a/PortProxyGUI/~DS/ListViewColumnSorter.cs +++ b/PortProxyGUI/UI/ListViewColumnSorter.cs @@ -1,7 +1,7 @@ using System.Collections; using System.Windows.Forms; -namespace PortProxyGUI +namespace PortProxyGUI.UI { public class ListViewColumnSorter : IComparer { @@ -68,7 +68,7 @@ namespace PortProxyGUI else if (OrderOfSort == SortOrder.Descending) { // Descending sort is selected, return negative result of compare operation - return (-compareResult); + return -compareResult; } else { diff --git a/PortProxyGUI/Utils/DnsUtil.cs b/PortProxyGUI/Utils/DnsUtil.cs new file mode 100644 index 0000000..1ade0fc --- /dev/null +++ b/PortProxyGUI/Utils/DnsUtil.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.InteropServices; + +namespace PortProxyGUI.Utils +{ + internal class DnsUtil + { + [DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache")] + static extern uint DnsFlushResolverCache(); + + public static void FlushCache() + { + var status = DnsFlushResolverCache(); + if (status == 0) throw new InvalidOperationException("Flush DNS Cache failed."); + } + + } +} diff --git a/PortProxyGUI/~DS/Util.cs b/PortProxyGUI/Utils/InterfaceUtil.cs similarity index 86% rename from PortProxyGUI/~DS/Util.cs rename to PortProxyGUI/Utils/InterfaceUtil.cs index 28307d6..f2b0122 100644 --- a/PortProxyGUI/~DS/Util.cs +++ b/PortProxyGUI/Utils/InterfaceUtil.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Drawing; using System.Text; -namespace PortProxyGUI +namespace PortProxyGUI.Utils { - public class Util + public class InterfaceUtil { /// /// Compatibility between .NET Framework and .NET Core. @@ -15,3 +15,4 @@ namespace PortProxyGUI } } + diff --git a/PortProxyGUI/Utils/PortPorxyUtil.cs b/PortProxyGUI/Utils/PortPorxyUtil.cs new file mode 100644 index 0000000..84717bc --- /dev/null +++ b/PortProxyGUI/Utils/PortPorxyUtil.cs @@ -0,0 +1,114 @@ +using Microsoft.Win32; +using PortProxyGUI.Data; +using PortProxyGUI.Native; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace PortProxyGUI.Utils +{ + public static class PortPorxyUtil + { + private static InvalidOperationException InvalidPortProxyType(string type) => new($"Invalid port proxy type ({type})."); + private static readonly string[] ProxyTypes = new[] { "v4tov4", "v4tov6", "v6tov4", "v6tov6" }; + + private static string GetKeyName(string type) + { + return $@"SYSTEM\CurrentControlSet\Services\PortProxy\{type}\tcp"; + } + + public static Rule[] GetProxies() + { + var ruleList = new List(); + foreach (var type in ProxyTypes) + { + var keyName = GetKeyName(type); + var key = Registry.LocalMachine.OpenSubKey(keyName); + + if (key is not null) + { + foreach (var name in key.GetValueNames()) + { + var listenParts = name.Split('/'); + var listenOn = listenParts[0]; + if (!int.TryParse(listenParts[1], out var listenPort)) continue; + + var connectParts = key.GetValue(name).ToString().Split('/'); + var connectTo = connectParts[0]; + if (!int.TryParse(connectParts[1], out var connectPort)) continue; + + ruleList.Add(new Rule + { + Type = type, + ListenOn = listenOn, + ListenPort = listenPort, + ConnectTo = connectTo, + ConnectPort = connectPort, + }); + } + } + } + return ruleList.ToArray(); + } + + public static void AddOrUpdateProxy(Rule rule) + { + // $"netsh interface portproxy add {rule.Type} listenaddress={rule.ListenOn} listenport={rule.ListenPort} connectaddress={rule.ConnectTo} connectport={rule.ConnectPort}" + + if (!ProxyTypes.Contains(rule.Type)) throw InvalidPortProxyType(rule.Type); + + var keyName = GetKeyName(rule.Type); + var key = Registry.LocalMachine.OpenSubKey(keyName, true); + var name = $"{rule.ListenOn}/{rule.ListenPort}"; + var value = $"{rule.ConnectTo}/{rule.ConnectPort}"; + + if (key is null) Registry.LocalMachine.CreateSubKey(keyName); + key = Registry.LocalMachine.OpenSubKey(keyName, true); + key?.SetValue(name, value); + } + + public static void DeleteProxy(Rule rule) + { + // $"netsh interface portproxy delete {rule.Type} listenaddress={rule.ListenOn} listenport={rule.ListenPort}" + + if (!ProxyTypes.Contains(rule.Type)) throw InvalidPortProxyType(rule.Type); + + var keyName = GetKeyName(rule.Type); + var key = Registry.LocalMachine.OpenSubKey(keyName, true); + var name = $"{rule.ListenOn}/{rule.ListenPort}"; + + try + { + key?.DeleteValue(name); + } + catch { } + } + + public static void ParamChange() + { + var hManager = NativeMethods.OpenSCManager(null, null, (uint)GenericRights.GENERIC_READ); + if (hManager == IntPtr.Zero) throw new InvalidOperationException("Open SC Manager failed."); + + var serviceName = "iphlpsvc"; + var hService = NativeMethods.OpenService(hManager, serviceName, ServiceRights.SERVICE_PAUSE_CONTINUE); + if (hService == IntPtr.Zero) + { + NativeMethods.CloseServiceHandle(hManager); + throw new InvalidOperationException($"Open Service ({serviceName}) failed."); + } + + var serviceStatus = new ServiceStatus(); + var success = NativeMethods.ControlService(hService, ServiceControls.SERVICE_CONTROL_PARAMCHANGE, ref serviceStatus); + + NativeMethods.CloseServiceHandle(hService); + NativeMethods.CloseServiceHandle(hManager); + + if (!success) + { + throw new InvalidOperationException($"Control Service ({serviceName}) ParamChange failed."); + } + } + + } +} diff --git a/PortProxyGUI/~DS/CmdRunner.cs b/PortProxyGUI/~DS/CmdRunner.cs deleted file mode 100644 index bb75e0c..0000000 --- a/PortProxyGUI/~DS/CmdRunner.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Diagnostics; - -namespace PortProxyGUI -{ - [Obsolete("The method of creating a new process is no longer used.")] - public static class CmdRunner - { - public static string Execute(string cmd) - { - var proc = Process.Start(new ProcessStartInfo - { - FileName = "cmd", - UseShellExecute = false, - RedirectStandardInput = true, - RedirectStandardOutput = true, - CreateNoWindow = true, - }); - proc.Start(); - - proc.StandardInput.WriteLine($"{cmd} & exit"); - var output = proc.StandardOutput.ReadToEnd(); - - return output; - } - } -} diff --git a/PortProxyGUI/~DS/CmdUtil.cs b/PortProxyGUI/~DS/CmdUtil.cs deleted file mode 100644 index 9c69d8e..0000000 --- a/PortProxyGUI/~DS/CmdUtil.cs +++ /dev/null @@ -1,89 +0,0 @@ -using NStandard; -using PortProxyGUI.Data; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; - -namespace PortProxyGUI -{ - [Obsolete("The method of creating a new process is no longer used.", true)] - public static class CmdUtil - { - private static Regex GetRegex(string fromType, string toType) - { - return new Regex($@"{fromType}[^:]*:[^\n]+?{toType}[^:]*:\r\n\r\n.+?\r\n--------------- ---------- --------------- ----------\r\n(.+?)\r\n\r\n", RegexOptions.Singleline); - } - - private static readonly Dictionary RegexList = new Dictionary() - { - ["ipv4 to ipv4"] = GetRegex("ipv4", "ipv4"), - ["ipv4 to ipv6"] = GetRegex("ipv4", "ipv6"), - ["ipv6 to ipv4"] = GetRegex("ipv6", "ipv4"), - ["ipv6 to ipv6"] = GetRegex("ipv6", "ipv6"), - }; - - private static readonly Regex LineRegex = new(@"^(.*?)\s{1,}(.*?)\s{1,}(.*?)\s{1,}(.*?)$"); - - public static Rule[] GetProxies() - { - var output = CmdRunner.Execute("netsh interface portproxy show all"); - var types = new[] - { - new ProxyType("ipv4", "ipv4"), - new ProxyType("ipv4", "ipv6"), - new ProxyType("ipv6", "ipv4"), - new ProxyType("ipv6", "ipv6"), - }; - - var list = new List(); - foreach (var type in types) - { - var regex = RegexList[$"{type.From} to {type.To}"]; - var settings = output.ExtractFirst(regex); - var lines = settings?.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - - if (lines is not null) - { - foreach (var line in lines) - { - if (line.TryResolve(LineRegex, out var parts)) - { - var realListenPort = parts[2].First(); - var realConnectPort = parts[4].First(); - - _ = int.TryParse(realListenPort, out var listenPort); - _ = int.TryParse(realConnectPort, out var connectPort); - - list.Add(new Rule - { - Type = type.Type, - ListenOn = parts[1].First(), - ListenPort = listenPort, - ConnectTo = parts[3].First(), - ConnectPort = connectPort, - }); - } - } - } - } - - return list.ToArray(); - } - - public static void AddOrUpdateProxy(Rule rule) - { - CmdRunner.Execute($"netsh interface portproxy add {rule.Type} listenaddress={rule.ListenOn} listenport={rule.ListenPort} connectaddress={rule.ConnectTo} connectport={rule.ConnectPort}"); - } - - public static void DeleteProxy(Rule rule) - { - CmdRunner.Execute($"netsh interface portproxy delete {rule.Type} listenaddress={rule.ListenOn} listenport={rule.ListenPort}"); - } - - public static string FlushDNSCache() - { - return CmdRunner.Execute("ipconfig /flushdns"); - } - } -} diff --git a/PortProxyGUI/~DS/PortProxyUtil.cs b/PortProxyGUI/~DS/PortProxyUtil.cs deleted file mode 100644 index b7fd22a..0000000 --- a/PortProxyGUI/~DS/PortProxyUtil.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Microsoft.Win32; -using PortProxyGUI.Data; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace PortProxyGUI -{ - public static class PortProxyUtil - { - private static InvalidOperationException InvalidPortProxyType(string type) => new($"Invalid port proxy type ({type})."); - private static readonly string[] ProxyTypes = new[] { "v4tov4", "v4tov6", "v6tov4", "v6tov6" }; - - public static Rule[] GetProxies() - { - var ruleList = new List(); - foreach (var type in ProxyTypes) - { - var keyName = $@"SYSTEM\ControlSet001\Services\PortProxy\{type}\tcp"; - var key = Registry.LocalMachine.OpenSubKey(keyName); - - if (key is not null) - { - foreach (var name in key.GetValueNames()) - { - var listenParts = name.Split('/'); - var listenOn = listenParts[0]; - if (!int.TryParse(listenParts[1], out var listenPort)) continue; - - var connectParts = key.GetValue(name).ToString().Split('/'); - var connectTo = connectParts[0]; - if (!int.TryParse(connectParts[1], out var connectPort)) continue; - - ruleList.Add(new Rule - { - Type = type, - ListenOn = listenOn, - ListenPort = listenPort, - ConnectTo = connectTo, - ConnectPort = connectPort, - }); - } - } - } - return ruleList.ToArray(); - } - - public static void AddOrUpdateProxy(Rule rule) - { - if (!ProxyTypes.Contains(rule.Type)) throw InvalidPortProxyType(rule.Type); - - var keyName = $@"SYSTEM\ControlSet001\Services\PortProxy\{rule.Type}\tcp"; - var key = Registry.LocalMachine.OpenSubKey(keyName, true); - var valueName = $"{rule.ListenOn}/{rule.ListenPort}"; - var value = $"{rule.ConnectTo}/{rule.ConnectPort}"; - - key.SetValue(valueName, value); - } - - public static void DeleteProxy(Rule rule) - { - if (!ProxyTypes.Contains(rule.Type)) throw InvalidPortProxyType(rule.Type); - - var keyName = $@"SYSTEM\ControlSet001\Services\PortProxy\{rule.Type}\tcp"; - var key = Registry.LocalMachine.OpenSubKey(keyName, true); - var valueName = $"{rule.ListenOn}/{rule.ListenPort}"; - - key.DeleteValue(valueName); - } - } -} diff --git a/PortProxyGUI/~DS/ProxyType.cs b/PortProxyGUI/~DS/ProxyType.cs deleted file mode 100644 index b157a51..0000000 --- a/PortProxyGUI/~DS/ProxyType.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -namespace PortProxyGUI -{ - public class ProxyType - { - public ProxyType(string from, string to) - { - From = from; - To = to; - } - - public string From { get; set; } - public string To { get; set; } - public string Type - { - get - { - if (From == "ipv4" && To == "ipv4") return "v4tov4"; - if (From == "ipv4" && To == "ipv6") return "v4tov6"; - if (From == "ipv6" && To == "ipv4") return "v6tov4"; - if (From == "ipv6" && To == "ipv6") return "v6tov6"; - throw new NotSupportedException(); - } - } - - } -} diff --git a/docs/ui.png b/docs/ui.png index 655a28a..008666c 100644 Binary files a/docs/ui.png and b/docs/ui.png differ