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 編輯過