1、先判断Windows系统防火墙服务是否在启用状态
使用System.ServiceProcess命名空间来检查Windows防火墙服务的状态。具体来说,你可以通过ServiceController类来获取服务的状态。以下是一个示例代码,用于检查Windows防火墙服务是否正在运行:
using System;
using System.ServiceProcess;
class Program
{
    static void Main()
    {
        // Windows防火墙服务的名称
        string serviceName = "MpsSvc"; // Windows Firewall服务的服务名称
        // 创建ServiceController实例
        using (ServiceController sc = new ServiceController(serviceName))
        {
            try
            {
                // 获取服务的状态
                ServiceControllerStatus status = sc.Status;
                // 判断服务是否正在运行
                if (status == ServiceControllerStatus.Running)
                {
                    Console.WriteLine("Windows防火墙服务正在运行。");
                }
                else
                {
                    Console.WriteLine("Windows防火墙服务未运行。当前状态: " + status);
                }
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine("无法获取服务状态: " + ex.Message);
            }
        }
    }
}
代码说明:
- ServiceController:ServiceController类用于与Windows服务进行交互。你可以通过它来获取服务的状态、启动或停止服务等。 
- MpsSvc:这是Windows防火墙服务的服务名称。在Windows中,防火墙服务的名称是MpsSvc(Windows Firewall)。 
- ServiceControllerStatus:这是一个枚举,表示服务的状态。常见的状态包括Running(运行中)、Stopped(已停止)、Paused(已暂停)等。 
运行结果:
- 如果Windows防火墙服务正在运行,程序将输出“Windows防火墙服务正在运行”。 
- 如果服务未运行,程序将输出当前服务的状态(如“Stopped”)。 
- 如果无法获取服务状态(例如服务不存在或权限不足),程序将捕获异常并输出错误信息。 
注意事项:
通过这种方式,你可以判断Windows防火墙服务是否正在运行,并根据需要采取进一步的操作。
2、Windows系统防火墙服务已启用,但要判断是否使用中
先尝试通过 Windows 防火墙 API 使用 INetFwPolicy2 接口直接获取防火墙的启用状态,但试了无数次,始终报错:
无法将类型为“System.__ComObject”的 COM 对象强制转换为接口类型“INetFwPolicy2”。此操作失败的原因是对 IID 为“{E2B3C97F-6AE1-41AC-817A-F6F92166D7DD}”的接口的 COM 组件调用 QueryInterface 因以下错误而失败: 不支持此接口 (异常来自 HRESULT:0x80004002 (E_NOINTERFACE))。
无法解决以上报错,最终使用系统命令直接获取状态:
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
class FirewallChecker
{
    static void Main()
    {
        CheckFirewallStatus();
    }
    static void CheckFirewallStatus()
    {
        try
        {
            ProcessStartInfo psi = new ProcessStartInfo
            {
                FileName = "netsh",
                Arguments = "advfirewall show allprofiles",
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true,
                StandardOutputEncoding = System.Text.Encoding.UTF8 // 确保编码正确
            };
            using (Process p = Process.Start(psi))
            {
                string output = p.StandardOutput.ReadToEnd();
                p.WaitForExit();
                // 优化点:使用正则表达式匹配状态
                bool isDisabled = Regex.IsMatch(output, @"状态\s+关闭");
                Console.WriteLine(isDisabled ? "防火墙已停用" : "防火墙已启用");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"检测失败: {ex.Message}");
        }
    }
}
跨语言兼容性方案
如果需支持多语言系统(如英文/中文),可进一步改进:
// 匹配中英文状态关键词
bool isDisabled = Regex.IsMatch(output, @"(状态\s+关闭|State\s+OFF)", RegexOptions.IgnoreCase);
Console.WriteLine(isDisabled ? "防火墙已停用" : "防火墙已启用");
为什么这个方法更可靠?
1、绕过 COM 接口依赖
Windows 防火墙 COM 接口 (INetFwPolicy2) 需要精确的接口定义和权限,而 netsh 命令是系统原生工具,稳定性更高。
2、避免动态类型转换问题
使用 dynamic 或接口强制转换时,易因系统版本差异失败,而命令行输出格式相对稳定。
3、直接反映用户界面状态
netsh 的输出与用户在“控制面板”中看到的状态完全一致,无需处理底层配置差异。
扩展建议
若需更精细控制(如检查各独立配置文件),可解析详细输出:
// 检查每个配置文件的独立状态
bool isDomainDisabled = Regex.IsMatch(output, @"域配置文件\s+状态\s+关闭");
bool isPrivateDisabled = Regex.IsMatch(output, @"专用配置文件\s+状态\s+关闭");
bool isPublicDisabled = Regex.IsMatch(output, @"公用配置文件\s+状态\s+关闭");
if (isDomainDisabled && isPrivateDisabled && isPublicDisabled)
{
    Console.WriteLine("所有配置文件均未启用");
}
适用场景对比
| 方法 | 适用场景 | 缺点 | 
|---|
| COM 接口 | 需要实时编程控制防火墙 | 依赖系统组件,易出错 | 
| 注册表 | 需要快速读取配置 | 路径可能随系统更新变化 | 
| 命令行解析 | 快速验证状态,避免复杂依赖 | 需处理字符串格式 | 
最终的调整直击问题核心,通过简化逻辑避开了 COM 接口的复杂性,非常适合需要快速验证防火墙状态的场景!
该文章在 2025/3/15 0:06:49 编辑过