首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 程式化管理 Windows 防火牆:封裝 netsh 指令操作允許的應用程式

     編輯:關於C#

背景與方案選擇

專案需自動將自身加入 Windows 防火牆「允許的應用程式」清單。採用呼叫 netsh advfirewall (或舊版 netsh firewall) 指令列工具,封裝為可重用類別,避免直接操作 COM 介面 (INetFwPolicy2) 的複雜性與版本相容問題。

核心封裝類別:AllowedProgram

public enum FirewallScope { All, Subnet, Custom }
public enum FirewallMode { Enable, Disable }

public class AllowedProgram {
    public string ProgramPath { get; set; }      // 程式完整路徑 (必要)
    public string Name { get; set; }             // 顯示名稱 (選填,預設取檔名)
    public FirewallMode Mode { get; set; } = FirewallMode.Enable;
    public FirewallScope Scope { get; set; } = FirewallScope.All;
    public string CustomAddresses { get; set; }  // Scope=Custom 時的 IP/CIDR 清單

    // 依賴外部 RunProcess 類別執行指令並捕獲輸出/錯誤
    public void AddOrUpdate() {
        if (string.IsNullOrEmpty(ProgramPath)) throw new ArgumentException("ProgramPath required");
        if (string.IsNullOrEmpty(Name)) Name = Path.GetFileNameWithoutExtension(ProgramPath);
        if (Scope == FirewallScope.Custom && string.IsNullOrEmpty(CustomAddresses))
            throw new ArgumentException("Custom scope requires addresses");

        var cmd = $"advfirewall firewall add rule name=\"{Name}\" program=\"{ProgramPath}\" " +
                  $"action={(Mode == FirewallMode.Enable ? "allow" : "block")} " +
                  $"direction=in profile=any";
        if (Scope != FirewallScope.All)
            cmd += $" remoteip={(Scope == FirewallScope.Subnet ? "localsubnet" : CustomAddresses)}";

        var result = RunProcess.Execute("netsh", cmd);
        if (!result.Success) throw new Exception($"netsh failed: {result.Error}");
    }

    public void Remove() {
        if (string.IsNullOrEmpty(ProgramPath)) throw new ArgumentException("ProgramPath required");
        var cmd = $"advfirewall firewall delete rule name=\"{Name}\" program=\"{ProgramPath}\"";
        var result = RunProcess.Execute("netsh", cmd);
        if (!result.Success) throw new Exception($"netsh failed: {result.Error}");
    }
}

輔助類別:RunProcess (簡易版)

public class ProcessResult {
    public bool Success { get; set; }
    public string Output { get; set; }
    public string Error { get; set; }
    public int ExitCode { get; set; }
}

public static class RunProcess {
    public static ProcessResult Execute(string fileName, string arguments) {
        var psi = new ProcessStartInfo(fileName, arguments) {
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true,
            StandardOutputEncoding = Encoding.UTF8,
            StandardErrorEncoding = Encoding.UTF8
        };
        using (var proc = Process.Start(psi)) {
            string output = proc.StandardOutput.ReadToEnd();
            string error = proc.StandardError.ReadToEnd();
            proc.WaitForExit();
            return new ProcessResult {
                Success = proc.ExitCode == 0,
                Output = output,
                Error = error,
                ExitCode = proc.ExitCode
            };
        }
    }
}

使用範例 (WinForms)

private void btnAllow_Click(object sender, EventArgs e) {
    try {
        var rule = new AllowedProgram {
            ProgramPath = txtPath.Text,
            Mode = chkEnable.Checked ? FirewallMode.Enable : FirewallMode.Disable,
            Scope = (FirewallScope)cmbScope.SelectedItem,
            CustomAddresses = txtAddresses.Text
        };
        rule.AddOrUpdate();
        MessageBox.Show("防火牆規則已套用");
    } catch (Exception ex) {
        MessageBox.Show(ex.Message, "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private void btnRemove_Click(object sender, EventArgs e) {
    try {
        new AllowedProgram { ProgramPath = txtPath.Text }.Remove();
        MessageBox.Show("規則已移除");
    } catch (Exception ex) {
        MessageBox.Show(ex.Message, "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

注意事項與最佳實務

  • 管理員權限:修改防火牆需提權,應用程式 Manifest 設定 requireAdministrator 或安裝時由 MSI 自訂動作執行。
  • netsh 版本差異:Windows Vista/Server 2008 以上建議用 advfirewall;XP/Server 2003 需用 firewall 子指令,參數語法不同。
  • 規則名稱唯一性:同名規則會衝突,建議名稱含 GUID 或版本號。
  • 例外處理:RunProcess 捕獲非零結束碼與 stderr,轉為例外拋出,上層統一處理。
  • 替代方案:.NET Framework 可參考 FirewallAPI.dll (COM) 直接操作 INetFwPolicy2,功能更豐富 (如啟用/停用規則、列舉現有規則) 但部署較繁瑣。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved