如何获取Windows防火墙出站规则名称列表?Delphi代码报错求助
解决Delphi获取防火墙出站规则名称时的"系统找不到指定文件"错误
问题根源
- 直接使用
OleVariant访问旧版HNetCfg.FwPolicy2COM对象,在Win10/Win11等新系统上存在兼容性问题,容易触发文件找不到的错误。 - 原代码使用
CoInitialize(nil)初始化COM,默认线程模型可能与防火墙API要求的单线程公寓模型不匹配,导致访问失败。 - 未检查COM对象/集合的有效性,直接访问引发异常。
解决方案
方案1:修复现有OleVariant代码
调整COM初始化方式,增加对象有效性检查,使用常量替代魔法数字:
const NET_FW_RULE_DIR_OUT = 2; // 出站规则方向常量 function GetOutboundFirewallRuleNames: TStringList; var i: Integer; fwPolicy2: OleVariant; rule: OleVariant; begin Result := TStringList.Create; try // 使用单线程公寓模型初始化COM,匹配防火墙API要求 if CoInitializeEx(nil, COINIT_APARTMENTTHREADED) <> S_OK then raise Exception.Create('COM初始化失败'); try fwPolicy2 := CreateOleObject('HNetCfg.FwPolicy2'); // 先验证Rules集合是否有效 if not VarIsNull(fwPolicy2.Rules) and (fwPolicy2.Rules.Count > 0) then begin // 从索引0开始遍历(COM集合通常以0为起始) for i := 0 to fwPolicy2.Rules.Count - 1 do begin rule := fwPolicy2.Rules.Item(i); // 确保rule对象有效再访问属性 if not VarIsNull(rule) then begin if rule.Direction = NET_FW_RULE_DIR_OUT then begin Result.Add(rule.Name); end; end; end; end; except on E: EOleException do begin Result.Free; raise Exception.CreateFmt('访问防火墙规则错误: %s', [E.Message]); end; on E: Exception do begin Result.Free; raise; end; end; finally CoUninitialize; end; end;
方案2:使用强类型NetFwTypeLib(推荐)
导入官方的Windows防火墙类型库,用强类型对象访问,避免OleVariant的兼容性问题:
导入类型库:
- 打开Delphi,依次点击
Component -> Import Component -> Import a Type Library - 在列表中找到
Windows Firewall with Advanced Security(或NetFwTypeLib),导入生成单元(默认命名为NetFwLib.pas)
- 打开Delphi,依次点击
实现代码:
uses SysUtils, Classes, ActiveX, NetFwLib; function GetOutboundFirewallRuleNames: TStringList; var i: Integer; fwPolicy2: INetFwPolicy2; rules: INetFwRules; rule: INetFwRule; begin Result := TStringList.Create; try // 初始化单线程公寓模型COM if CoInitializeEx(nil, COINIT_APARTMENTTHREADED) <> S_OK then raise Exception.Create('COM初始化失败'); try // 创建强类型防火墙策略对象 fwPolicy2 := CoNetFwPolicy2.Create; rules := fwPolicy2.Rules; for i := 0 to rules.Count - 1 do begin rule := rules.Item(i); if rule.Direction = NET_FW_RULE_DIR_OUT then begin Result.Add(rule.Name); end; end; except on E: EOleException do begin Result.Free; raise Exception.CreateFmt('访问防火墙规则错误: %s', [E.Message]); end; on E: Exception do begin Result.Free; raise; end; end; finally CoUninitialize; end; end;
注意事项
- 必须以管理员权限运行程序,否则会被系统拒绝访问防火墙规则。
- 确保Windows Firewall服务(
MpsSvc)处于运行状态。 - 编译时注意目标平台(32/64位),避免与COM对象位数不匹配。
内容的提问来源于stack exchange,提问作者Shaun Roselt
相关产品推荐
相关产品推荐

