[英]Automating Windows Firewall with
我有 C# 應用程序,它使用端口 777 進行異步通信,使用端口 3306 與我的 Sql 服務器進行通信。 當端口被防火牆阻止時,就會出現問題。 我試圖創建一個程序來在 Windows 7 的防火牆列表中添加一個例外。
當我運行該程序時,出現如下錯誤:“災難性故障(HRESULT 異常:0x8000FFFF(E_UNEXPECTED))”。
我不明白這些錯誤是什么意思,歡迎任何建議,謝謝。
protected internal void AddExceptionToFirewall(){
try {
INetFwMgr fireWall = null;
INetFwAuthorizedApplications apps = null;
INetFwAuthorizedApplication app = null;
Type progID = null;
INetFwOpenPorts ports = null;
INetFwOpenPort asyncPort = null;
INetFwOpenPort mysqlPort = null;
bool appFounded = false;
bool asyncPortFounded = false;
bool mysqlPortFounded = false;
progID = Type.GetTypeFromProgID("HNetCfg.FwMgr");
// checking for Windows Firewall
fireWall = (INetFwMgr)Activator.CreateInstance(progID);
if (fireWall.LocalPolicy.CurrentProfile.FirewallEnabled) {
// obtain the list of authorized applications
apps = (INetFwAuthorizedApplications)fireWall.LocalPolicy.CurrentProfile.AuthorizedApplications;
IEnumerator appEnumerate = apps.GetEnumerator();
while (appEnumerate.MoveNext()){
app = (INetFwAuthorizedApplication)appEnumerate.Current;
if (app.Name == Application.ProductName){
appFounded = true;
break;
}
}
// add this application to the list of authorized applications
if(appFounded==false){
app.Name = Application.ProductName;
StringBuilder strBuild = new StringBuilder();
strBuild.Append(Application.ExecutablePath.Replace("\\","\\\\"));
app.ProcessImageFileName = strBuild.ToString();
app.Enabled = true;
apps = (INetFwAuthorizedApplications)fireWall.LocalPolicy.CurrentProfile.AuthorizedApplications;
apps.Add(app);
}
// obtain the list of authorized asynchronous socket ports (777)
ports = (INetFwOpenPorts)fireWall.LocalPolicy.CurrentProfile.GloballyOpenPorts;
IEnumerator portEnumerate = ports.GetEnumerator();
while (portEnumerate.MoveNext()) {
asyncPort = (INetFwOpenPort)portEnumerate.Current;
if (asyncPort.Port == 777) {
asyncPortFounded = true;
break;
}
}
// add a port 777 to globally open ports
if (asyncPortFounded==false)
ports.Add(asyncPort);
// obtain the list of authorized mysql socket ports(3306)
while (portEnumerate.MoveNext()) {
mysqlPort = (INetFwOpenPort)portEnumerate.Current;
if (mysqlPort.Port == 3306) {
mysqlPortFounded = true;
break;
}
}
// add a port 3306 to globally open ports
if (mysqlPortFounded == false)
ports.Add(mysqlPort);
}
}
catch (COMException cm) {
MessageBox.Show(cm.Message);
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
http://www.codeproject.com/Articles/14906/Open-Windows-Firewall-During-Installation
在使用下面的程序之前,請將參考FirewallAPI.dll添加到Visual Studio 2010.執行以下操作:在Visual Studio 2010的解決方案資源管理器中右鍵單擊項目 - 選擇添加引用 - 選擇C:\\ Windows \\ System32 \\ FirewallAPI。 dll - 好的
使用以下3行代碼調用程序防火牆。 您可以將此代碼放在程序的表單加載中:
private clsFirewall objFirewall = new clsFirewall(); objFirewall.CloseFirewall(); objFirewall.OpenFirewall();
/ *使用C#自動化Windows防火牆支持Windows 7 * /
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Threading;
using NetFwTypeLib;
using System.Windows.Forms;
namespace MyFirewall {
public class clsFirewall {
private int[] portsSocket = { 777, 3306 };
private string[] portsName = { "AsyncPort", "MySqlPort" };
private INetFwProfile fwProfile = null;
protected internal void OpenFirewall() {
INetFwAuthorizedApplications authApps = null;
INetFwAuthorizedApplication authApp = null;
INetFwOpenPorts openPorts = null;
INetFwOpenPort openPort = null;
try {
if (isAppFound(Application.ProductName + " Server") == false) {
SetProfile();
authApps = fwProfile.AuthorizedApplications;
authApp = GetInstance("INetAuthApp") as INetFwAuthorizedApplication;
authApp.Name = Application.ProductName + " Server";
authApp.ProcessImageFileName = Application.ExecutablePath;
authApps.Add(authApp);
}
if (isPortFound(portsSocket[0]) == false) {
SetProfile();
openPorts = fwProfile.GloballyOpenPorts;
openPort = GetInstance("INetOpenPort") as INetFwOpenPort;
openPort.Port = portsSocket[0];
openPort.Protocol = NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
openPort.Name = portsName[0];
openPorts.Add(openPort);
}
if (isPortFound(portsSocket[1]) == false) {
SetProfile();
openPorts = fwProfile.GloballyOpenPorts;
openPort = GetInstance("INetOpenPort") as INetFwOpenPort;
openPort.Port = portsSocket[1];
openPort.Protocol = NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
openPort.Name = portsName[1];
openPorts.Add(openPort);
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
finally {
if (authApps != null) authApps = null;
if (authApp != null) authApp = null;
if (openPorts != null) openPorts = null;
if (openPort != null) openPort = null;
}
}
protected internal void CloseFirewall() {
INetFwAuthorizedApplications apps = null;
INetFwOpenPorts ports = null;
try {
if (isAppFound(Application.ProductName + " Server") == true) {
SetProfile();
apps = fwProfile.AuthorizedApplications;
apps.Remove(Application.ExecutablePath);
}
if (isPortFound(portsSocket[0]) == true) {
SetProfile();
ports = fwProfile.GloballyOpenPorts;
ports.Remove(portsSocket[0], NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP);
}
if (isPortFound(portsSocket[1]) == true) {
SetProfile();
ports = fwProfile.GloballyOpenPorts;
ports.Remove(portsSocket[1], NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP);
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
finally {
if (apps != null) apps = null;
if (ports != null) ports = null;
}
}
protected internal bool isAppFound(string appName) {
bool boolResult = false;
Type progID = null;
INetFwMgr firewall = null;
INetFwAuthorizedApplications apps = null;
INetFwAuthorizedApplication app = null;
try {
progID = Type.GetTypeFromProgID("HNetCfg.FwMgr");
firewall = Activator.CreateInstance(progID) as INetFwMgr;
if (firewall.LocalPolicy.CurrentProfile.FirewallEnabled) {
apps = firewall.LocalPolicy.CurrentProfile.AuthorizedApplications;
IEnumerator appEnumerate = apps.GetEnumerator();
while ((appEnumerate.MoveNext())) {
app = appEnumerate.Current as INetFwAuthorizedApplication;
if (app.Name == appName) {
boolResult = true;
break;
}
}
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
finally {
if (progID != null) progID = null;
if (firewall != null) firewall = null;
if (apps != null) apps = null;
if (app != null) app = null;
}
return boolResult;
}
protected internal bool isPortFound(int portNumber) {
bool boolResult = false;
INetFwOpenPorts ports = null;
Type progID = null;
INetFwMgr firewall = null;
INetFwOpenPort currentPort = null;
try {
progID = Type.GetTypeFromProgID("HNetCfg.FwMgr");
firewall = Activator.CreateInstance(progID) as INetFwMgr;
ports = firewall.LocalPolicy.CurrentProfile.GloballyOpenPorts;
IEnumerator portEnumerate = ports.GetEnumerator();
while ((portEnumerate.MoveNext())) {
currentPort = portEnumerate.Current as INetFwOpenPort;
if (currentPort.Port == portNumber) {
boolResult = true;
break;
}
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
finally
{
if (ports != null) ports = null;
if (progID != null) progID = null;
if (firewall != null) firewall = null;
if (currentPort != null) currentPort = null;
}
return boolResult;
}
protected internal void SetProfile() {
INetFwMgr fwMgr = null;
INetFwPolicy fwPolicy = null;
try {
fwMgr = GetInstance("INetFwMgr") as INetFwMgr;
fwPolicy = fwMgr.LocalPolicy;
fwProfile = fwPolicy.CurrentProfile;
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
finally {
if (fwMgr != null) fwMgr = null;
if (fwPolicy != null) fwPolicy = null;
}
}
protected internal object GetInstance(string typeName) {
Type tpResult = null;
switch (typeName) {
case "INetFwMgr":
tpResult = Type.GetTypeFromCLSID(new Guid("{304CE942-6E39-40D8-943A-B913C40C9CD4}"));
return Activator.CreateInstance(tpResult);
case "INetAuthApp":
tpResult = Type.GetTypeFromCLSID(new Guid("{EC9846B3-2762-4A6B-A214-6ACB603462D2}"));
return Activator.CreateInstance(tpResult);
case "INetOpenPort":
tpResult = Type.GetTypeFromCLSID(new Guid("{0CA545C6-37AD-4A6C-BF92-9F7610067EF5}"));
return Activator.CreateInstance(tpResult);
default:
return null;
}
}
}
}
Javanese Girl接受的答案有一個類似C的實現,具有無聲明使用模式和冗余代碼。 這是基於該答案的重構實現。 它使用所有相同的調用FirewallAPI.dll; 它在功能上是等價的,因此它解決了原始問題無法使這些類型的防火牆操作起作用的問題。 此解決方案具有隱藏所有詳細信息的簡單界面:IsPortOpen,OpenPort和ClosePort。
用法示例:
int port = 9914;
if (IsPortOpen(port))
ClosePort(port);
OpenPort(port, "StreamBeam API");
執行:
using System;
using System.Collections;
using NetFwTypeLib;
namespace YourCompany
{
public static class FirewallUtils
{
public static bool IsPortOpen(int port)
{
EnsureSetup();
Type progID = Type.GetTypeFromProgID("HNetCfg.FwMgr");
INetFwMgr firewall = Activator.CreateInstance(progID) as INetFwMgr;
INetFwOpenPorts ports = firewall.LocalPolicy.CurrentProfile.GloballyOpenPorts;
IEnumerator portEnumerate = ports.GetEnumerator();
while ((portEnumerate.MoveNext()))
{
INetFwOpenPort currentPort = portEnumerate.Current as INetFwOpenPort;
if (currentPort.Port == port)
return true;
}
return false;
}
public static void OpenPort(int port, string applicationName)
{
EnsureSetup();
if (IsPortOpen(port))
return;
INetFwOpenPort openPort = GetInstance("INetOpenPort") as INetFwOpenPort;
openPort.Port = port;
openPort.Protocol = NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
openPort.Name = applicationName;
INetFwOpenPorts openPorts = sm_fwProfile.GloballyOpenPorts;
openPorts.Add(openPort);
}
public static void ClosePort(int port)
{
EnsureSetup();
if (!IsPortOpen(port))
return;
INetFwOpenPorts ports = sm_fwProfile.GloballyOpenPorts;
ports.Remove(port, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP);
}
private static object GetInstance(string typeName)
{
Type tpResult = null;
switch (typeName)
{
case "INetFwMgr":
tpResult = Type.GetTypeFromCLSID(new Guid("{304CE942-6E39-40D8-943A-B913C40C9CD4}"));
return Activator.CreateInstance(tpResult);
case "INetAuthApp":
tpResult = Type.GetTypeFromCLSID(new Guid("{EC9846B3-2762-4A6B-A214-6ACB603462D2}"));
return Activator.CreateInstance(tpResult);
case "INetOpenPort":
tpResult = Type.GetTypeFromCLSID(new Guid("{0CA545C6-37AD-4A6C-BF92-9F7610067EF5}"));
return Activator.CreateInstance(tpResult);
default:
throw new Exception("Unknown type name: " + typeName);
}
}
private static void EnsureSetup()
{
if (sm_fwProfile != null)
return;
INetFwMgr fwMgr = GetInstance("INetFwMgr") as INetFwMgr;
sm_fwProfile = fwMgr.LocalPolicy.CurrentProfile;
}
private static INetFwProfile sm_fwProfile = null;
}
}
我是通過Google來到這里尋找一種列出Windows防火牆開放端口的.net方法。 上述答案無效。 具體來說,firewall.LocalPolicy.CurrentProfile.GloballyOpenPorts的計數總是為零。 這些答案很老,可能適用於Windows 7.在Windows 10上對我有用的是這段代碼。
using System;
using System.Collections;
using NetFwTypeLib;
namespace FirewallPorts
{
class FwPorts
{
static void Main(string[] args)
{
Type fwPolicy2Type = Type.GetTypeFromProgID("HNetCfg.FwPolicy2", true);
INetFwPolicy2 fwPolicy = (INetFwPolicy2)Activator.CreateInstance(fwPolicy2Type);
int currentProfs = fwPolicy.CurrentProfileTypes;
NET_FW_PROFILE_TYPE2_ foo = (NET_FW_PROFILE_TYPE2_)currentProfs;
if (foo.HasFlag(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE))
Console.WriteLine("PrivateNet");
if (!foo.HasFlag(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PUBLIC))
Console.WriteLine("NOT PUBLIC");
bool fpsEnabled = fwPolicy.IsRuleGroupCurrentlyEnabled["File and Printer Sharing"];
bool FwEnabled = fwPolicy.FirewallEnabled[NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PUBLIC] || fwPolicy.FirewallEnabled[NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE];
Console.WriteLine($"Windows Firewall enabled is {FwEnabled}");
INetFwRules rules = fwPolicy.Rules;
foreach (INetFwRule item in rules)
{
if (item.Enabled && item.Name.Contains("Sharing"))
{
Console.WriteLine(item.Name);
Console.WriteLine($"LocalPorts: {item.LocalPorts}, {(NET_FW_PROFILE_TYPE2_)item.Profiles}");
Console.WriteLine(item.Description + "\r\n");
}
}
}
}
}
我不需要打開或關閉端口,但可以通過更改規則狀態,或創建新規則並啟用它們來完成。 希望這可以節省其他人幾個小時。
我正在尋找一種使用 C# 程序創建防火牆規則的解決方案。 我找到了很多似乎有效的解決方案,但是當我嘗試在我的程序中運行該程序時,它並沒有奏效。 所以我搜索了這個問題。
解決方案:需要以管理員權限啟動Visual Studio。
遍歷包括本地端口等在內的防火牆規則列表的解決方案可能是:
void SetRecommendedSetting(List<FirewallModel> fwList)
{
foreach (var firewallModel in fwList)
{
INetFwRule firewallRule = (INetFwRule)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FWRule"));
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
if (!string.IsNullOrEmpty(firewallModel.Name))
firewallRule.Name = firewallModel.Name;
if (firewallModel.Protocol.ToLower().Contains("udp"))
{
if (firewallModel.Protocol.ToLower().Contains("tcp"))
{
if (firewallModel.Protocol.ToLower().Contains("domain"))
{
firewallRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_ANY;
}
}
else
{
firewallRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP;
}
}
else if (firewallModel.Protocol.ToLower().Equals("tcp"))
{
firewallRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
}
else
{
firewallRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_ANY;
}
if (firewallModel.Direction.Equals("in"))
firewallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
else
firewallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT;
if (firewallModel.Action.ToLower().Equals("allow"))
firewallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
else firewallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_BLOCK;
firewallRule.Profiles = (int)NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_ALL;
if (firewallModel.Description != null || firewallModel.Description != "")
firewallRule.Description = firewallModel.Description;
if (firewallModel.Enable.Equals("yes"))
firewallRule.Enabled = true;
firewallRule.LocalPorts = firewallModel.LocalPorts;
firewallPolicy.Rules.Add(firewallRule);
}
}
此代碼為我運行。 我添加了一個 app.manifest 並將 requestlevel 更改為 ,以便我的應用程序即使在調試模式下也能以 adminpermission 運行。
希望這個解決方案對你有用!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.