1、先判斷Windows系統(tǒng)防火墻服務(wù)是否在啟用狀態(tài)
使用System.ServiceProcess命名空間來檢查Windows防火墻服務(wù)的狀態(tài)。具體來說,你可以通過ServiceController類來獲取服務(wù)的狀態(tài)。以下是一個(gè)示例代碼,用于檢查Windows防火墻服務(wù)是否正在運(yùn)行:
using System;
using System.ServiceProcess;
class Program
{
static void Main()
{
// Windows防火墻服務(wù)的名稱
string serviceName = "MpsSvc"; // Windows Firewall服務(wù)的服務(wù)名稱
// 創(chuàng)建ServiceController實(shí)例
using (ServiceController sc = new ServiceController(serviceName))
{
try
{
// 獲取服務(wù)的狀態(tài)
ServiceControllerStatus status = sc.Status;
// 判斷服務(wù)是否正在運(yùn)行
if (status == ServiceControllerStatus.Running)
{
Console.WriteLine("Windows防火墻服務(wù)正在運(yùn)行。");
}
else
{
Console.WriteLine("Windows防火墻服務(wù)未運(yùn)行。當(dāng)前狀態(tài): " + status);
}
}
catch (InvalidOperationException ex)
{
Console.WriteLine("無法獲取服務(wù)狀態(tài): " + ex.Message);
}
}
}
}
代碼說明:
ServiceController:ServiceController類用于與Windows服務(wù)進(jìn)行交互。你可以通過它來獲取服務(wù)的狀態(tài)、啟動(dòng)或停止服務(wù)等。
MpsSvc:這是Windows防火墻服務(wù)的服務(wù)名稱。在Windows中,防火墻服務(wù)的名稱是MpsSvc(Windows Firewall)。
ServiceControllerStatus:這是一個(gè)枚舉,表示服務(wù)的狀態(tài)。常見的狀態(tài)包括Running(運(yùn)行中)、Stopped(已停止)、Paused(已暫停)等。
運(yùn)行結(jié)果:
如果Windows防火墻服務(wù)正在運(yùn)行,程序?qū)⑤敵觥癢indows防火墻服務(wù)正在運(yùn)行”。
如果服務(wù)未運(yùn)行,程序?qū)⑤敵霎?dāng)前服務(wù)的狀態(tài)(如“Stopped”)。
如果無法獲取服務(wù)狀態(tài)(例如服務(wù)不存在或權(quán)限不足),程序?qū)⒉东@異常并輸出錯(cuò)誤信息。
注意事項(xiàng):
通過這種方式,你可以判斷Windows防火墻服務(wù)是否正在運(yùn)行,并根據(jù)需要采取進(jìn)一步的操作。
2、Windows系統(tǒng)防火墻服務(wù)已啟用,但要判斷是否使用中
先嘗試通過 Windows 防火墻 API 使用 INetFwPolicy2 接口直接獲取防火墻的啟用狀態(tài),但試了無數(shù)次,始終報(bào)錯(cuò):
無法將類型為“System.__ComObject”的 COM 對象強(qiáng)制轉(zhuǎn)換為接口類型“INetFwPolicy2”。此操作失敗的原因是對 IID 為“{E2B3C97F-6AE1-41AC-817A-F6F92166D7DD}”的接口的 COM 組件調(diào)用 QueryInterface 因以下錯(cuò)誤而失敗: 不支持此接口 (異常來自 HRESULT:0x80004002 (E_NOINTERFACE))。
無法解決以上報(bào)錯(cuò),最終使用系統(tǒng)命令直接獲取狀態(tài):
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();
// 優(yōu)化點(diǎn):使用正則表達(dá)式匹配狀態(tài)
bool isDisabled = Regex.IsMatch(output, @"狀態(tài)\s+關(guān)閉");
Console.WriteLine(isDisabled ? "防火墻已停用" : "防火墻已啟用");
}
}
catch (Exception ex)
{
Console.WriteLine($"檢測失敗: {ex.Message}");
}
}
}
跨語言兼容性方案
如果需支持多語言系統(tǒng)(如英文/中文),可進(jìn)一步改進(jìn):
// 匹配中英文狀態(tài)關(guān)鍵詞
bool isDisabled = Regex.IsMatch(output, @"(狀態(tài)\s+關(guān)閉|State\s+OFF)", RegexOptions.IgnoreCase);
Console.WriteLine(isDisabled ? "防火墻已停用" : "防火墻已啟用");
為什么這個(gè)方法更可靠?
1、繞過 COM 接口依賴
Windows 防火墻 COM 接口 (INetFwPolicy2
) 需要精確的接口定義和權(quán)限,而 netsh
命令是系統(tǒng)原生工具,穩(wěn)定性更高。
2、避免動(dòng)態(tài)類型轉(zhuǎn)換問題
使用 dynamic
或接口強(qiáng)制轉(zhuǎn)換時(shí),易因系統(tǒng)版本差異失敗,而命令行輸出格式相對穩(wěn)定。
3、直接反映用戶界面狀態(tài)
netsh
的輸出與用戶在“控制面板”中看到的狀態(tài)完全一致,無需處理底層配置差異。
擴(kuò)展建議
若需更精細(xì)控制(如檢查各獨(dú)立配置文件),可解析詳細(xì)輸出:
// 檢查每個(gè)配置文件的獨(dú)立狀態(tài)
bool isDomainDisabled = Regex.IsMatch(output, @"域配置文件\s+狀態(tài)\s+關(guān)閉");
bool isPrivateDisabled = Regex.IsMatch(output, @"專用配置文件\s+狀態(tài)\s+關(guān)閉");
bool isPublicDisabled = Regex.IsMatch(output, @"公用配置文件\s+狀態(tài)\s+關(guān)閉");
if (isDomainDisabled && isPrivateDisabled && isPublicDisabled)
{
Console.WriteLine("所有配置文件均未啟用");
}
適用場景對比
方法 | 適用場景 | 缺點(diǎn) |
---|
COM 接口 | 需要實(shí)時(shí)編程控制防火墻 | 依賴系統(tǒng)組件,易出錯(cuò) |
注冊表 | 需要快速讀取配置 | 路徑可能隨系統(tǒng)更新變化 |
命令行解析 | 快速驗(yàn)證狀態(tài),避免復(fù)雜依賴 | 需處理字符串格式 |
最終的調(diào)整直擊問題核心,通過簡化邏輯避開了 COM 接口的復(fù)雜性,非常適合需要快速驗(yàn)證防火墻狀態(tài)的場景!
該文章在 2025/3/15 0:06:49 編輯過