From 9fc03d55e2909ec198406697fd684b22abae0ad8 Mon Sep 17 00:00:00 2001 From: JanitorialMess <65749353+JanitorialMess@users.noreply.github.com> Date: Sun, 29 Mar 2026 16:36:02 -0400 Subject: [PATCH 1/6] refactor: use COM API for windows firewall rules --- ServerPickerX/ServerPickerX.csproj | 2 + .../SystemFirewalls/WindowsFirewallService.cs | 158 +++++++++++------- 2 files changed, 103 insertions(+), 57 deletions(-) diff --git a/ServerPickerX/ServerPickerX.csproj b/ServerPickerX/ServerPickerX.csproj index 62d2272..d4eabbb 100644 --- a/ServerPickerX/ServerPickerX.csproj +++ b/ServerPickerX/ServerPickerX.csproj @@ -6,6 +6,8 @@ true true + + true partial diff --git a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs index 433da09..a6bd377 100644 --- a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs +++ b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs @@ -20,73 +20,68 @@ public class WindowsFirewallService( IProcessService _processService ) : ISystemFirewallService { - public async Task BlockServersAsync(ObservableCollection serverModels) + private const string FirewallPolicyProgId = "HNetCfg.FwPolicy2"; + private const string FirewallRuleProgId = "HNetCfg.FWRule"; + private const string FirewallRulePrefix = "server_picker_x_"; + private const int FirewallRuleDirectionOutbound = 2; + private const int FirewallRuleActionBlock = 0; + private const int FirewallRuleProtocolAny = 256; + private const int FirewallRuleProfilesAll = int.MaxValue; + + public Task BlockServersAsync(ObservableCollection serverModels) { - foreach (var serverModel in serverModels) - { - string ipAddresses = string.Join(",", serverModel.RelayModels.Select(s => s.IPv4).ToList()); - - using var process = _processService.CreateProcess("cmd.exe"); - - process.StartInfo.Arguments = $"/c {Path.Combine(Environment.SystemDirectory, "netsh.exe")} " + - "advfirewall firewall " + - "add rule " + - "name=server_picker_x_" + serverModel.Description.Replace(" ", "") + - " dir=out action=block protocol=ANY " + "remoteip=" + ipAddresses; - - try - { - process.Start(); - await process.WaitForExitAsync(); - - string stdOut = process.StandardOutput.ReadToEnd().Trim(); - string stdErr = process.StandardError.ReadToEnd().Trim(); + dynamic firewallRules = GetFirewallRules(); - if (process.ExitCode > 0) - { - await _loggerService.LogWarningAsync("StdOut: " + stdOut + " StdErr: " + stdErr); - } - } - catch (Exception ex) + try + { + foreach (var serverModel in serverModels) { - // Perform debugging here if necessary (log error or through debugger breakpoints) - throw; + string ruleName = GetFirewallRuleName(serverModel); + string ipAddresses = string.Join(",", serverModel.RelayModels.Select(s => s.IPv4).ToList()); + + RemoveFirewallRuleByName(firewallRules, ruleName); + + dynamic firewallRule = CreateFirewallRule(); + firewallRule.Name = ruleName; + firewallRule.Description = serverModel.Description; + firewallRule.Direction = FirewallRuleDirectionOutbound; + firewallRule.Action = FirewallRuleActionBlock; + firewallRule.Protocol = FirewallRuleProtocolAny; + firewallRule.RemoteAddresses = ipAddresses; + firewallRule.Enabled = true; + firewallRule.Profiles = FirewallRuleProfilesAll; + + firewallRules.Add(firewallRule); } } - } - - public async Task UnblockServersAsync(ObservableCollection serverModels) - { - foreach (var serverModel in serverModels) + catch (Exception) { - string ipAddresses = string.Join(",", serverModel.RelayModels.Select(s => s.IPv4).ToList()); - - using var process = _processService.CreateProcess("cmd.exe"); - - process.StartInfo.Arguments = $"/c {Path.Combine(Environment.SystemDirectory, "netsh.exe")} " + - "advfirewall firewall " + - "delete rule " + - "name=server_picker_x_" + serverModel.Description.Replace(" ", ""); + // Perform debugging here if necessary (log error or through debugger breakpoints) + throw; + } - try - { - process.Start(); - await process.WaitForExitAsync(); + return Task.CompletedTask; + } - string stdOut = process.StandardOutput.ReadToEnd().Trim(); - string stdErr = process.StandardError.ReadToEnd().Trim(); + public Task UnblockServersAsync(ObservableCollection serverModels) + { + dynamic firewallRules = GetFirewallRules(); - if (process.ExitCode > 0) - { - await _loggerService.LogWarningAsync("StdOut: " + stdOut + " StdErr: " + stdErr); - } - } - catch (Exception ex) + try + { + foreach (var serverModel in serverModels) { - // Perform debugging here if necessary (log error or through debugger breakpoints) - throw; + string ruleName = GetFirewallRuleName(serverModel); + RemoveFirewallRuleByName(firewallRules, ruleName); } } + catch (Exception) + { + // Perform debugging here if necessary (log error or through debugger breakpoints) + throw; + } + + return Task.CompletedTask; } public async Task ResetFirewallAsync() @@ -125,11 +120,60 @@ await _messageBoxService.ShowMessageBoxAsync( MsBox.Avalonia.Enums.Icon.Success ); } - catch (Exception ex) + catch (Exception) { // Perform debugging here if necessary (log error or through debugger breakpoints) throw; } } + + private static dynamic CreateComObject(string progId) + { + Type? comType = Type.GetTypeFromProgID(progId); + + if (comType == null) + { + throw new InvalidOperationException($"Unable to resolve COM ProgID '{progId}'."); + } + + return Activator.CreateInstance(comType) + ?? throw new InvalidOperationException($"Unable to create COM instance for '{progId}'."); + } + + private static dynamic GetFirewallRules() + { + dynamic firewallPolicy = CreateComObject(FirewallPolicyProgId); + return firewallPolicy.Rules; + } + + private static dynamic CreateFirewallRule() + { + return CreateComObject(FirewallRuleProgId); + } + + private static string GetFirewallRuleName(ServerModel serverModel) + { + return FirewallRulePrefix + serverModel.Description.Replace(" ", ""); + } + + private static void RemoveFirewallRuleByName(dynamic firewallRules, string ruleName) + { + while (TryGetFirewallRule(firewallRules, ruleName) != null) + { + firewallRules.Remove(ruleName); + } + } + + private static dynamic? TryGetFirewallRule(dynamic firewallRules, string ruleName) + { + try + { + return firewallRules.Item(ruleName); + } + catch + { + return null; + } + } } -} \ No newline at end of file +} From 2cba1aea50ca3e118ca2e02e1aac9a6156920084 Mon Sep 17 00:00:00 2001 From: JanitorialMess <65749353+JanitorialMess@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:22:53 -0400 Subject: [PATCH 2/6] refactor: rename firewall COM API helpers --- .../SystemFirewalls/WindowsFirewallService.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs index a6bd377..8175342 100644 --- a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs +++ b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs @@ -30,7 +30,8 @@ IProcessService _processService public Task BlockServersAsync(ObservableCollection serverModels) { - dynamic firewallRules = GetFirewallRules(); + dynamic firewallPolicy = GetFirewallPolicyApi(); + dynamic firewallRules = firewallPolicy.Rules; try { @@ -41,7 +42,7 @@ public Task BlockServersAsync(ObservableCollection serverModels) RemoveFirewallRuleByName(firewallRules, ruleName); - dynamic firewallRule = CreateFirewallRule(); + dynamic firewallRule = CreateFirewallRuleApi(); firewallRule.Name = ruleName; firewallRule.Description = serverModel.Description; firewallRule.Direction = FirewallRuleDirectionOutbound; @@ -65,7 +66,8 @@ public Task BlockServersAsync(ObservableCollection serverModels) public Task UnblockServersAsync(ObservableCollection serverModels) { - dynamic firewallRules = GetFirewallRules(); + dynamic firewallPolicy = GetFirewallPolicyApi(); + dynamic firewallRules = firewallPolicy.Rules; try { @@ -140,13 +142,12 @@ private static dynamic CreateComObject(string progId) ?? throw new InvalidOperationException($"Unable to create COM instance for '{progId}'."); } - private static dynamic GetFirewallRules() + private static dynamic GetFirewallPolicyApi() { - dynamic firewallPolicy = CreateComObject(FirewallPolicyProgId); - return firewallPolicy.Rules; + return CreateComObject(FirewallPolicyProgId); } - private static dynamic CreateFirewallRule() + private static dynamic CreateFirewallRuleApi() { return CreateComObject(FirewallRuleProgId); } From bf90a8baac69f64de23aae195e5235364548f768 Mon Sep 17 00:00:00 2001 From: FN-FAL113 Date: Tue, 31 Mar 2026 12:02:06 +0800 Subject: [PATCH 3/6] refactor: exception handling --- .../SystemFirewalls/WindowsFirewallService.cs | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs index 8175342..64f331e 100644 --- a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs +++ b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs @@ -28,13 +28,13 @@ IProcessService _processService private const int FirewallRuleProtocolAny = 256; private const int FirewallRuleProfilesAll = int.MaxValue; - public Task BlockServersAsync(ObservableCollection serverModels) + public async Task BlockServersAsync(ObservableCollection serverModels) { - dynamic firewallPolicy = GetFirewallPolicyApi(); - dynamic firewallRules = firewallPolicy.Rules; - try { + dynamic firewallPolicy = GetFirewallPolicyApi(); + dynamic firewallRules = firewallPolicy.Rules; + foreach (var serverModel in serverModels) { string ruleName = GetFirewallRuleName(serverModel); @@ -55,35 +55,33 @@ public Task BlockServersAsync(ObservableCollection serverModels) firewallRules.Add(firewallRule); } } - catch (Exception) + catch (Exception ex) { // Perform debugging here if necessary (log error or through debugger breakpoints) + await _loggerService.LogErrorAsync(ex.Message); throw; } - - return Task.CompletedTask; } - public Task UnblockServersAsync(ObservableCollection serverModels) + public async Task UnblockServersAsync(ObservableCollection serverModels) { - dynamic firewallPolicy = GetFirewallPolicyApi(); - dynamic firewallRules = firewallPolicy.Rules; - try { + dynamic firewallPolicy = GetFirewallPolicyApi(); + dynamic firewallRules = firewallPolicy.Rules; + foreach (var serverModel in serverModels) { string ruleName = GetFirewallRuleName(serverModel); RemoveFirewallRuleByName(firewallRules, ruleName); } } - catch (Exception) + catch (Exception ex) { // Perform debugging here if necessary (log error or through debugger breakpoints) + await _loggerService.LogErrorAsync(ex.Message); throw; } - - return Task.CompletedTask; } public async Task ResetFirewallAsync() @@ -122,9 +120,10 @@ await _messageBoxService.ShowMessageBoxAsync( MsBox.Avalonia.Enums.Icon.Success ); } - catch (Exception) + catch (Exception ex) { // Perform debugging here if necessary (log error or through debugger breakpoints) + await _loggerService.LogErrorAsync(ex.Message); throw; } } From e6ce51deb838d3f5a7e65e41e125406c41e0215c Mon Sep 17 00:00:00 2001 From: FN-FAL113 Date: Tue, 31 Mar 2026 12:27:38 +0800 Subject: [PATCH 4/6] chore: bump assembly version --- ServerPickerX/ServerPickerX.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ServerPickerX/ServerPickerX.csproj b/ServerPickerX/ServerPickerX.csproj index d4eabbb..2d55f8c 100644 --- a/ServerPickerX/ServerPickerX.csproj +++ b/ServerPickerX/ServerPickerX.csproj @@ -22,8 +22,8 @@ https://github.com/FN-FAL113/server-picker-x https://github.com/FN-FAL113/server-picker-x Assets\favicon.ico - 1.0.3.0 - 1.0.3.0 + 1.0.4.0 + 1.0.4.0 From 5f6f919d0dc2828e6916f64446ae3235fe4e49a1 Mon Sep 17 00:00:00 2001 From: FN-FAL113 Date: Tue, 31 Mar 2026 14:50:50 +0800 Subject: [PATCH 5/6] refactor: use Interop.NetFwTypeLib.dll assembly for static types --- ServerPickerX/ServerPickerX.csproj | 4 + .../SystemFirewalls/WindowsFirewallService.cs | 70 +++++------------- ServerPickerX/libs/Interop.NetFwTypeLib.dll | Bin 0 -> 22016 bytes 3 files changed, 23 insertions(+), 51 deletions(-) create mode 100644 ServerPickerX/libs/Interop.NetFwTypeLib.dll diff --git a/ServerPickerX/ServerPickerX.csproj b/ServerPickerX/ServerPickerX.csproj index 2d55f8c..64d084c 100644 --- a/ServerPickerX/ServerPickerX.csproj +++ b/ServerPickerX/ServerPickerX.csproj @@ -33,6 +33,10 @@ + + libs\Interop.NetFwTypeLib.dll + true + diff --git a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs index 64f331e..998acfc 100644 --- a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs +++ b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs @@ -10,6 +10,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using NetFwTypeLib; namespace ServerPickerX.Services.SystemFirewalls { @@ -20,11 +21,9 @@ public class WindowsFirewallService( IProcessService _processService ) : ISystemFirewallService { - private const string FirewallPolicyProgId = "HNetCfg.FwPolicy2"; - private const string FirewallRuleProgId = "HNetCfg.FWRule"; private const string FirewallRulePrefix = "server_picker_x_"; - private const int FirewallRuleDirectionOutbound = 2; - private const int FirewallRuleActionBlock = 0; + private const NET_FW_RULE_DIRECTION_ FirewallRuleDirectionOutbound = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT; + private const NET_FW_ACTION_ FirewallRuleActionBlock = NET_FW_ACTION_.NET_FW_ACTION_BLOCK; private const int FirewallRuleProtocolAny = 256; private const int FirewallRuleProfilesAll = int.MaxValue; @@ -32,17 +31,17 @@ public async Task BlockServersAsync(ObservableCollection serverMode { try { - dynamic firewallPolicy = GetFirewallPolicyApi(); - dynamic firewallRules = firewallPolicy.Rules; + INetFwPolicy2 firewallPolicy = GetFirewallPolicyApi(); + INetFwRules firewallRules = firewallPolicy.Rules; foreach (var serverModel in serverModels) { string ruleName = GetFirewallRuleName(serverModel); - string ipAddresses = string.Join(",", serverModel.RelayModels.Select(s => s.IPv4).ToList()); + string ipAddresses = string.Join(",", serverModel.RelayModels.Select(s => s.IPv4)); RemoveFirewallRuleByName(firewallRules, ruleName); - dynamic firewallRule = CreateFirewallRuleApi(); + INetFwRule firewallRule = CreateFirewallRuleApi(); firewallRule.Name = ruleName; firewallRule.Description = serverModel.Description; firewallRule.Direction = FirewallRuleDirectionOutbound; @@ -57,7 +56,6 @@ public async Task BlockServersAsync(ObservableCollection serverMode } catch (Exception ex) { - // Perform debugging here if necessary (log error or through debugger breakpoints) await _loggerService.LogErrorAsync(ex.Message); throw; } @@ -67,8 +65,8 @@ public async Task UnblockServersAsync(ObservableCollection serverMo { try { - dynamic firewallPolicy = GetFirewallPolicyApi(); - dynamic firewallRules = firewallPolicy.Rules; + INetFwPolicy2 firewallPolicy = GetFirewallPolicyApi(); + INetFwRules firewallRules = firewallPolicy.Rules; foreach (var serverModel in serverModels) { @@ -78,7 +76,6 @@ public async Task UnblockServersAsync(ObservableCollection serverMo } catch (Exception ex) { - // Perform debugging here if necessary (log error or through debugger breakpoints) await _loggerService.LogErrorAsync(ex.Message); throw; } @@ -92,10 +89,7 @@ public async Task ResetFirewallAsync() MsBox.Avalonia.Enums.Icon.Warning ); - if (!result) - { - return; - } + if (!result) return; using Process process = _processService.CreateProcess("cmd.exe"); @@ -122,41 +116,21 @@ await _messageBoxService.ShowMessageBoxAsync( } catch (Exception ex) { - // Perform debugging here if necessary (log error or through debugger breakpoints) await _loggerService.LogErrorAsync(ex.Message); throw; } } - private static dynamic CreateComObject(string progId) - { - Type? comType = Type.GetTypeFromProgID(progId); - - if (comType == null) - { - throw new InvalidOperationException($"Unable to resolve COM ProgID '{progId}'."); - } - - return Activator.CreateInstance(comType) - ?? throw new InvalidOperationException($"Unable to create COM instance for '{progId}'."); - } - - private static dynamic GetFirewallPolicyApi() - { - return CreateComObject(FirewallPolicyProgId); - } + private static INetFwPolicy2 GetFirewallPolicyApi() + => (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("E2B3C97F-6AE1-41AC-817A-F6F92166D7DD"))!)!; - private static dynamic CreateFirewallRuleApi() - { - return CreateComObject(FirewallRuleProgId); - } + private static INetFwRule CreateFirewallRuleApi() + => (INetFwRule)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("2C5BC43E-3369-4C33-AB0C-BE9469677AF4"))!)!; private static string GetFirewallRuleName(ServerModel serverModel) - { - return FirewallRulePrefix + serverModel.Description.Replace(" ", ""); - } + => FirewallRulePrefix + serverModel.Description.Replace(" ", ""); - private static void RemoveFirewallRuleByName(dynamic firewallRules, string ruleName) + private static void RemoveFirewallRuleByName(INetFwRules firewallRules, string ruleName) { while (TryGetFirewallRule(firewallRules, ruleName) != null) { @@ -164,16 +138,10 @@ private static void RemoveFirewallRuleByName(dynamic firewallRules, string ruleN } } - private static dynamic? TryGetFirewallRule(dynamic firewallRules, string ruleName) + private static INetFwRule? TryGetFirewallRule(INetFwRules firewallRules, string ruleName) { - try - { - return firewallRules.Item(ruleName); - } - catch - { - return null; - } + try { return firewallRules.Item(ruleName); } + catch { return null; } } } } diff --git a/ServerPickerX/libs/Interop.NetFwTypeLib.dll b/ServerPickerX/libs/Interop.NetFwTypeLib.dll new file mode 100644 index 0000000000000000000000000000000000000000..d52e0edf2b7f1ba61c599597e5d0ebe68b494e9c GIT binary patch literal 22016 zcmeHvdw5)BwfDRC&Q2!HrMWZ(q>%wiOKc~dOeUEbp@+G*V=t+>lwN>lI+>xfnkX&Eez7k%NNQa1$Z|2N4wz_zu(#=&>3znK$Z;A=g zcR&-H&VM*#mG)oa6laB6A;d;lN)78(gZOr`9#rUybk(RgQK~yYjir zQ2z);3}AjZ@O^4em&ik>(K~fbPa=x%E5N(Uz{3OCo#6CAGi%O1Yg{QO^5$u+0{KxJ zsO(0_2OthIK#-K>WPINPem%bHAy+_NhL~Z{wl5}~CgTFNRxK6BtIL2f#%+w}vpuU` z3j0-zpJn^)>O-*njPZAD(X?eeu11d3H@Biu3&c|7PfUTM1*`#jIkPCUQZS0_ zrA^kzk$H}+5Gy(I_f~>0HZc+<;X^prA>B(eHWPQaZYy`r)w0?uT2yQv`;oQ=_$$U&8Ouu6 z2+P}8vJT#6#3462@zQmiJ4G9)$N^#$N$xc55{cRh_6U zz`V0qleUmI4#OAH8u(gauyxw|M2U>tt~s%qt#ny!skw1eo`VXfHz8by)+YTS?1%_`Qd|f`e1GrSiUN1kw-Eb=~l_ED|ZU7WVe+s6>XAH z``RU=_W2~E_W32F_VMMGYewz+p!8Au&XA1Sccx_2z5=5bt+sp^zX=-~cPthEBz;F6 zw~MnRqt=Ebd#U^`5teM(g8M|=VpaYH5198vRu3jDAIf_~6d0BFA?Z8ncucI5jLO?! zG49=sl2Pw=NVZ{t)4X+}^3KIQ>4&8+2VbXT2jJtoLhixO!e`t{QM#|f*CQim%C?Ek zlKr{tJRAES(w!}RQ%JW(vS;DjD%qdl+a_5_g;Q*o?6``h;vC6nG|!ccM)N$$+K_IC zWb2TwSF(|cCq+`S%PW2(c1m__#j}F$F^!r0g^CwMpJewU&$MJeL7uxLquJ9h8O@#o zdll(+OW!+4myxW#a+^3`GH2y^HWsRE5__bttI}m->B^V*{?VxCaOEGxpp2wdH6$60 zdsZ?U_hHFs+%J%f#yuw)jXU3l%5l$2AC3E{WHjyVhaW60$_fJV5jr*r1OI2+X zS4sAfs`G4&=ENcCqd9T4WHcwPk&NcVzeq-N;#$dQPFyD$?FH9MMswmblF^*FK{A>X z1x9n?u=LTKxKT2i6Q7lg=EUbDqdD<;$!Jd8BpJ<#nG!+#`LLE^HF_ zN_J?W%f^ntcc1j#3txdv!*{>*y$N4|HP$qV?@Qmt8kdb-R#UG`O5Y7N$16XOjP85> zmt(qlm{jIS#4DLp~du>+Jy3u#i|~DNMaxm{7Sq2`msfrv*~4|0D!-QOH+7dQzqMG^TXk33*rNJRDNjkCtNu#m8Oheb_nc(O z`sf9zJ^C^EZy)c<&T!H>N5?`ioZxU z(eQ%!t7H#1IK>;1{jy=HcvG^!!1tD9ba(hSi|I{^Us4L}sN*%|9qFU{GxH}VJ?#)a zja{twXu?TMaVlcJM&6^0_mzXYe z^ta(vMfm~+zwKWtSMZy@b^*m(_Cl()Y`53M(hD(`g>o2NP_WxeN6rG{ZuKD|pRh&R z^$%1Oa@cR18_5c4i9jxjIAn{t!=^u7LEfXbR27wEaWTR!bGWp!P|E+C^`~}SU-kc6 zD}HNhQC)SRb!Q(_H~T@3tg(AMzL4yTY78{;`FoJ!->fZ0wJ@XXUaX)yc)k_lRdG$- z?6gK5>@kaK>@}fy%unQYKhkRALC(Rl6lSbF2h3jC-eNng!TakBuUU!_3Hw7>gDUo3 zD#htgoFyXGpx_Cf=1`rbqO(DDmWge!(Ed#IA+IK0hPQ;hI=n`nRLZ?J{Y6tRcs+|v z9l3qb)E#)*Q~{}iEQHjHAf9Qh$J3(|@Dwb#cqzVvi{DUA2A+rK2c#!}?=Lk(-1I z-YslDhwZ&=-_7v@Y#(O(#ccTqTgKRO1xJ30EmyPUI?nB|@F34|j{hQizXC5kU2DYs zGGQ~GJ*j2Qcn0JFRtN|13=u60vNwW$TC7E2|AU%Mn0gKQZG?$eIIURrvD?GtR7WSjyX(54xmVed1D zbeGP+g1Tws)ikb~Rw1^Pmc!DhIf3|{1YD*CSx*30X}!S1T8iUSh`*vV1B+i9WBYzs zzEQfLy$500qm2U_wIi@UQF?^!6R_m9Nw!Y`_i59>W!el7FI!7UF9)Iyz*Slk>p|8N zK+G$kU(2v%jP-+zWHfllE6Rh_F4`>L*J)4fmlJn16mNcOiKU{ zX}!QzS_XJn8w2{agTNK~IO`KYuRaOfqfG%<>(i{y0OPtS<5mDWbSLXgz%6;Z(60#x#g_y3XinCffO#zl zL@R*%v|iRTzysPCaFuotct{&(eFAt`n*{o`Dc}lyn)Ml=R~O}!b2)Ie?qt0Q7}tZq zyp{lV=)J6GfLru2V54>rnAFFC%d`pL`T8Vql{N*uNuLH{uK;4K7f_4D0%}n?5GxLd zu>fMlu_Xb-iepO#xJMfUq7-0W8wa8k;67~x3 zCOyb{0{E!j3(RX7;FJ0o>j!~P>*K(E+63@LeUkMl;Ggtq-~nw0__i*pNG}Is-2t)o zfmr*jCxBS{z{6Swi1p6;K_J#RaD_er#JXmE3W#+L^y)J}tm|sh%Ylb9Cvdgi1U#$- zSx*2PwO(Lc&#*qm`a$3_Z5-I4PXJeGldMkx{n|8ei#`L~qlty2mjm;f6PVPSfcvx{ z>j~fitrvK{o&kFGG1ds8n{mriwT`T?17BEz(d*?<2Vqz1miStg)WXGbOOD4 zkg*qtRl_(A#7Hqt13PqaJfRbaJ&>^%nAFD@$AQ=-7^i_Z>EZ-JC-6}{$k+?Ss$m=l zKCMqOP6J=m#rp`Iz(46h#$Mpt`WWLl5O*&?+^aB(6S;pFgFx&sjAKBo7sg2-u1!Gn z&l2hxC-9IK1RmCUf#`oA=0EF`tWPtFM$Vrx2t@vjV?gB3I0;1ljN<*=|3LIV5LX`{ zt~)?nae%niFirzk>*6FrClI?a5c@C?^#P(jK&(U{)*uk8&q-bDz3idR3KO_U$ z0~v)}1i2LcefYi%-!II(?;G*`ImF$B?^__ZLXJSb z1UU+sfP4*dJLC??oshdAcSF7lxd(C|4Nk?l8_W64e5tuAbTK# zkSyc^$OzYvS-P;gFJwsLTYfi_%Qv7~%;FLi*P7~1MmrA_5 zufm)6YP@e>h_~!Dc(-1U_sEOz=CuLu0FT4_wd2KzI1%rtmf&4fBfn+xX&(GG?a_R| z+qE-+N3|gEky64}8Q*0*4!?zPLW;42F~hi@ah&lxjL())K1R+yM+$n-u^TwIl$aw3 z`}f#uqMF*!jU2cpH?w7e z@h(QAXOa~Z|6t``fp=8A4Sbp{MvwhFNB+E$S~^`B1YTOHC<0FqDb;&Z*3DH^`g>oZ zvXI(X&v**s2N}B7%oj1Iw z;RWFS2CC1!4K$7~Hcl4q(fGXrT=!=0WJIkRj z$1b5@w`hXiBvwHG08oXvfGcrwM#XuV7NAG80$XtkM#VE6A0pd;D$cxe+PK0y;x8f{_g0mYv(6{5Xhk~;jXG1?19tCGJwnEm z4tt z;9UpfRj{dek570A9tH2_KMDOB*c7~r|1|V#;ZgAJo$xd8sCe^Ecmq5N-lks*{YKan zygk1j`sd(L@V5L0=r_Tm;O+R0&~Jf95#vA=Z^3VZ{so|lx8Aov{~}PuTkcz-f0^+s z@Zh;G;{-ek-d7WT9X1v3rwMPv8*K&eoF|~)4x56v%3p(i2RsViA`^ZK9u@D93GaeO z!CT@xpx+Ifg15qVLjNv23f}wP1^pg)@N5;R;vMdHq2CWw@m}^G=#xNI`~V&W?_ckO z{s26Rc#!cScvSI2#vj3>;O#2mzrm)8DaMDzk6`)VKvg^fnP^D|5Wj`cn0{4cnhonxa6{psR`w zT?4A3L@5L6O1V-ph9Kvk#1F{vuAy5M>NqH zi*(z2A!JgsJCVR+buIK(Q{R-!?#dMMLO;Y4$j;udO<7cbuNBY4W0h@>_s9X*&=F0< zx9;fb4t2|M*wCM|vdCeeQ~6>xA_hlN+1vmIwqxh{X}G)gj^xvWV$Eo#FO)}D>>SOf zO=ENC=ukd0m~KuC<kMKcArdF=#$i*biO;A4QKl2ws=$0 z<}DhFW6Uj%k@JGtJmX%JQ_-jvdFG5)k+*0x>?IZVwcRtP8|_YeHx(6B)Ctsq8!^wg zuUKIqGv-}Bo5~KbOOnj6R5^$)(X@j2T21@r#?ir@=^U@K@MvZrpBNG{1qWHy!o7jK zuy;o`S^I$fdfyYB*GyXx)ggk-AumFGeS$W;3)3RO*Q9jbc6~5nD4I5KBiZOkK08Pk zf2M2jXLregfxU&h3XY5vqUJ`JO|b4X_^KS*7{#4RVq;;KGw(xsHf@y6uu^o!Hgw?f z8;y0X>+YE2-Po})X7z`af-m~CJ&s(Ml1)Jer*O$g3?}>2aoj1$5uMkODGHl6Bsn~c z&NOartlO#);{wik!*7{7YRFyBDYEVA=H z_&CURZzdZy+eVq$D@d8yIr-OTQ^^6Eg2t8AMho-SxTqQz&O)f2%bYObY}aYdtzg2R zt0o7C8X3|JE{)bmXs9oOKN>b_FxNWQ!o9>7D!Mi0K9URF_#?8+)B22g-z3w{@|l^C zm18L%V+1MhS;16^V>$~dH{kX#Gn77N;`#lQo_`Lc;{(ZlqtoqtZlB3E8C@jltb&hO zW5Y3jZR{me&ElB47vUOZ-QQDJ%(hV+-EtbUW@9$b*M9T%b6yAjTLUYG5+g}wm-$n8 z1V76PKQHF@^jRU4xMv6{NAkEB4C5DCdZatMVRRtRws0<+>?3DUp8rq+D#7Tl;ztf- zFM5PPhA!*(CXvEu*fxz3F}w5T?VtIZ{SQ@qzDgHWSXTBJ6*ada>z91AV?(I08(CKT zl;0Q)bw;gS#j;0wIy+;9`w`15?vVi#s2Z#&0uv6-(bW)E7oA#|}cmI>W) z@J=uK=|U#b{DWB}Mx?`9PLwvAOY;)8W=1rCLjt)GS>`X*u2}S7Lpq0X2%nI4zE0?o9XNqK{h!>>KGR?oqgmM;kf&fb2gvgojzFN6t$JQQ&DOw zNv&bE2Fa>RV629slA@M45JymhzjUdFsA{Q0E3K`B)KJPLoN@^gI4FUGVwWI}g4kDg ze5q4a9JNczoNC?i_(rO_MoM}*X--OTI-t&p6sMOumAa+1r&FeNZeX3ey3ARkR9CC2 z?o`!kR8Q2MN#SR5Ops!NWUY;op*D(|pa?~wa%$JIZ7r1%MWvRIvKHk;A!{jM3+0EJ zi@HSwD+#<5wS~%{*1!Q+N#I2)PS8!&>^5S$QG{CCM~$rQLnW0Z7U7oqOP!kHsOH)` zs9zPNtzBE&hweZEs)eF*{demQ$_R)Ys5pPAgCk2|uZE#^H_GpW?50|tQ|&BMs%tA9 z)wN4%@UOzDV=$|A(kb;hRF%46VBIhps3@gSmD(nBqvCLs(EKQ&w-+TUfkseDP)k7X zHA*O^$GB>h2Ie;H2&4tGZ-C5E%Cv%zP zP+mr?bk0t)(rG>jUQPc&5dKlfKz=lrUOki^&F7K>E1jE0cjA%#y7b=e?4I<{>YeV^ zU2VI3yINZM+T6+3q)<*&PH0lZ(x^8ai$tSwS9{#o>hgyCt*)@Y)#D08+S~m;ZzSq* z$M7y+5y2Y%&wz}#Ir#G~>Jzq5zp%m`CMeTTyT|PddtxphvUYhr?IBm7ttIAai?u|; zk+x7g7K(Bb-AYUS$`<2K&yc^vvKW8B1d-fn9JMh4!PhCx!eJFB)<- z;PM6hUVjYvw8zkelxMgt*6xj?HW5#x&4nytu28GH#TAFc?RK~L-ED3ovK>B@?{P&U z@qo+gZ;!YFzL3Y&8i=>HdD?vLaH|>V_q6-M;aICH?hl|t0xc0&*cWbhd7|N#Slk_J zi+aLFo`Hxr((dv3Ty1WT52a&3Lh(?{6$!P(+q|A=$n6dok)gP!)g47pI1~=KyfLrG z6^g{7u6Ucr8~1o3@rc=L#-Em<`;5P1*-( zTiOEwbX^>gZT>J;Z~#*!j$y*Q^2L2^Mr3Os7H(~ixm_N2029C+j=E5U$JO2%YH1B) zTD7(#Po38`)wa#QYiDYgFXc-6l4w^uG{1Xit7})Py)EtEl}aVuej)HjUzJ7ITETxb z$o*(Q?_hy^lyql-+qK#MznTzu_?n9j3~WedhK!ek>9le6MzXcHBA*~F*LSDwxx808 zoeIJkC2aY{CE|@X3|O6W>=d^avIQReHG};4H81qdI1{r27{mXi(uMOg9r$nU@Gcq{ zH~$}&`$}HHp9WLzB=j-9&oT(ENjN!W>ed(bSwwBd*_a&i$>0PG9$@3_%P#Z(_*lxR zy5UX2Is$(Zr(QDf4sjNjiEox1My3ktlt)ws_WpTt%5#hx?e-yWH%=Vwq&~ojCpwoE zL4Jeymquzl(1+a#S!(kQbNPGG+9b!p%`q!E#;SP~IgH?J57lG1sGgLc8y5{l)@?Il z@leUumKOYC&sgLXFK z9MS;((dTro?|S(9IX7zgFrul({bD!L+uK!$Ge)2f=?0N5hx16(OGfNDT+a?O4;lfg zr`0FKsAq+(C4YZ?KaP=7@IU+HP|rS`WJ;li_Av;d9wS_ Date: Tue, 31 Mar 2026 15:19:24 +0800 Subject: [PATCH 6/6] chore: private property naming convention --- .../SystemFirewalls/WindowsFirewallService.cs | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs index 998acfc..4684002 100644 --- a/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs +++ b/ServerPickerX/Services/SystemFirewalls/WindowsFirewallService.cs @@ -21,11 +21,11 @@ public class WindowsFirewallService( IProcessService _processService ) : ISystemFirewallService { - private const string FirewallRulePrefix = "server_picker_x_"; - private const NET_FW_RULE_DIRECTION_ FirewallRuleDirectionOutbound = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT; - private const NET_FW_ACTION_ FirewallRuleActionBlock = NET_FW_ACTION_.NET_FW_ACTION_BLOCK; - private const int FirewallRuleProtocolAny = 256; - private const int FirewallRuleProfilesAll = int.MaxValue; + private const string _firewallRulePrefix = "server_picker_x_"; + private const NET_FW_RULE_DIRECTION_ _firewallRuleDirectionOutbound = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT; + private const NET_FW_ACTION_ _firewallRuleActionBlock = NET_FW_ACTION_.NET_FW_ACTION_BLOCK; + private const int _firewallRuleProtocolAny = 256; + private const int _firewallRuleProfilesAll = int.MaxValue; public async Task BlockServersAsync(ObservableCollection serverModels) { @@ -44,12 +44,12 @@ public async Task BlockServersAsync(ObservableCollection serverMode INetFwRule firewallRule = CreateFirewallRuleApi(); firewallRule.Name = ruleName; firewallRule.Description = serverModel.Description; - firewallRule.Direction = FirewallRuleDirectionOutbound; - firewallRule.Action = FirewallRuleActionBlock; - firewallRule.Protocol = FirewallRuleProtocolAny; + firewallRule.Direction = _firewallRuleDirectionOutbound; + firewallRule.Action = _firewallRuleActionBlock; + firewallRule.Protocol = _firewallRuleProtocolAny; firewallRule.RemoteAddresses = ipAddresses; firewallRule.Enabled = true; - firewallRule.Profiles = FirewallRuleProfilesAll; + firewallRule.Profiles = _firewallRuleProfilesAll; firewallRules.Add(firewallRule); } @@ -121,16 +121,16 @@ await _messageBoxService.ShowMessageBoxAsync( } } - private static INetFwPolicy2 GetFirewallPolicyApi() + public INetFwPolicy2 GetFirewallPolicyApi() => (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("E2B3C97F-6AE1-41AC-817A-F6F92166D7DD"))!)!; - private static INetFwRule CreateFirewallRuleApi() + public INetFwRule CreateFirewallRuleApi() => (INetFwRule)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("2C5BC43E-3369-4C33-AB0C-BE9469677AF4"))!)!; - private static string GetFirewallRuleName(ServerModel serverModel) - => FirewallRulePrefix + serverModel.Description.Replace(" ", ""); + public string GetFirewallRuleName(ServerModel serverModel) + => _firewallRulePrefix + serverModel.Description.Replace(" ", ""); - private static void RemoveFirewallRuleByName(INetFwRules firewallRules, string ruleName) + public void RemoveFirewallRuleByName(INetFwRules firewallRules, string ruleName) { while (TryGetFirewallRule(firewallRules, ruleName) != null) { @@ -138,10 +138,14 @@ private static void RemoveFirewallRuleByName(INetFwRules firewallRules, string r } } - private static INetFwRule? TryGetFirewallRule(INetFwRules firewallRules, string ruleName) + public INetFwRule? TryGetFirewallRule(INetFwRules firewallRules, string ruleName) { - try { return firewallRules.Item(ruleName); } - catch { return null; } + try + { + return firewallRules.Item(ruleName); + } catch { + return null; + } } } }