问题:
目前公司软件刚由单机软件更改为联网软件,许多客户反映希望能够有一个功能来控制电脑上某些必用软件,如qq,公司软件联网,而其他不必要的如网页,游戏等软件不允许联网,于是向公司反映希望可以有一个功能能够实现这种需求。
开始思路:
刚开始接到任务的时候首先想到是控制防火墙来进行此项操作。于是打开自己电脑的防火墙,设置了出站规则——新建规则——禁用所有程序联网,然后单独设置两个例外,测试结果为所有程序都连不上网,于是这个思路放弃。
然后思考用c#写程序来监控任务管理器中程序的添加,如果不是qq或者是我们软件的话,就会kill程序,结果杀伤力巨大,就连打开我的电脑都打不开了,于是这个思路也走不通。
最后还是回到了防火墙的层面:首先新建规则—禁用1—65535的所有端口,然后开启qq所用的4000—4100端口和软件所用的8080端口。测试结果成功。
参考代码:
https://www.cnblogs.com/shenblogs/archive/2016/05/13/5489161.html 写的很全,并且有关闭防火墙的功能
c#程序:
主要添加引用:
1.com组件NetFwTypeLib
2.System.ServiceProcess
应注意:在添加禁用端口的规则时,应该注意要先添加规则的协议为TCP还是Udp,不然可能会报:值不在预期的范围内。
主要程序如下:
1 using Microsoft.Win32;
2 using NetFwTypeLib;
3 using System;
4 using System.Collections.Generic;
5 using System.Diagnostics;
6 using System.Linq;
7 using System.ServiceProcess;
8 using System.Text;
9 using System.Threading.Tasks;
10
11 namespace Control_Firewall
12 {
13 class Program
14 {
15 RegistryKey firekey;
16 //获取防火墙名称
17 string firewallname = "";
18 //电脑名称
19 string versionname = "";
20 //获取电脑版本名称
21 public string getsysversion()
22 {
23 RegistryKey rk = Registry.LocalMachine.OpenSubKey(@"Software\\Microsoft\\Windows NT\\CurrentVersion");
24 versionname = rk.GetValue("ProductName").ToString();
25 rk.Close();
26 return versionname;
27 }
28 //根据电脑类型来操作防火墙打开
29 public void openfire(string versionname)
30 {
31 if (versionname.Contains("XP"))
32 {
33 firewallname = "SharedAccess";
34 firekey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\\CurrentControlSet\\Services\\SharedAccess", true);
35 }
36 else
37 {
38 firewallname = "MpsSvc";
39 firekey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\\CurrentControlSet\\Services\\MpsSvc", true);
40 }
41 //获取启动类型为禁止还是自动
42 string start = firekey.GetValue("Start").ToString();
43 if (start == "4") {
44 ProcessStartInfo objProInfo = new ProcessStartInfo();
45 objProInfo.FileName = "cmd.exe";
46 objProInfo.CreateNoWindow = false;
47 objProInfo.WindowStyle = ProcessWindowStyle.Hidden;
48 objProInfo.Arguments = "/c sc config " + firewallname + " start= " + "auto";
49 Process.Start(objProInfo);
50 //挂起线程1s后启动服务
51 System.Threading.Thread.Sleep(1000);
52 }
53 firekey.Close();
54 //判断防火墙是否启动了
55 ServiceController sc = new ServiceController(firewallname);
56 //如果防火墙未启动则启动
57 if (sc.Status.Equals(ServiceControllerStatus.Stopped) || sc.Status.Equals(ServiceControllerStatus.StopPending))
58 {
59 sc.Start();
60 }
61 //暂时不用
62 if (versionname.Contains("XP"))
63 {
64 RegistryKey rekey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\StandardProfile", true);
65 var Enablefilewall = rekey.GetValue("EnableFirewall").ToString();
66 if (Enablefilewall == "0")
67 {
68 rekey.SetValue("EnableFirewall", 1);
69 }
70 rekey.Close();
71 }
72 else
73 {
74 INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
75 // 启用<高级安全Windows防火墙> - 专有配置文件的防火墙
76 firewallPolicy.set_FirewallEnabled(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE, true);
77 // 启用<高级安全Windows防火墙> - 公用配置文件的防火墙
78 firewallPolicy.set_FirewallEnabled(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PUBLIC, true);
79 }
80 }
81 //为防火墙添加出站规则
82 public void handle(string name)
83 {
84 //目前不用
85 if (name.Contains("XP"))
86 {
87 INetFwAuthorizedApplication Fwapp = (INetFwAuthorizedApplication)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwAuthorizedApplication"));
88 }
89
90 else
91 {
92 // 1. 创建实例,阻止所有的出站连接
93 INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
94 //启用或禁用<高级安全Windows防火墙> - 专有配置文件的出站连接
95 firewallPolicy.set_DefaultOutboundAction(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE, NET_FW_ACTION_.NET_FW_ACTION_ALLOW);
96 //启用或禁用<高级安全Windows防火墙> - 公用配置文件的出站连接
97 firewallPolicy.set_DefaultOutboundAction(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PUBLIC, NET_FW_ACTION_.NET_FW_ACTION_ALLOW);
98 //创建三个出站规则来控制程序联网
99 INetFwRule2 qqRule = (INetFwRule2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
100 INetFwRule2 conductRule = (INetFwRule2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
101 INetFwRule2 stopallRule = (INetFwRule2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
102 stopallRule.Name = "禁用所有端口号";
103 stopallRule.Description = "关闭所有可用端口";
104 stopallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT;
105 stopallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_BLOCK;
106 stopallRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
107 stopallRule.Enabled = true;
108 stopallRule.RemotePorts = "1-65535";
109
110 //开启qq端口
111 qqRule.Name = "启用qq";
112 qqRule.Description = "开启qq所用的4000-4100端口";
113 qqRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT;
114 qqRule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
115 qqRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
116 qqRule.Enabled = true;
117 qqRule.RemotePorts = "4000-4100";
118
119 //开启所用软件端口
120 conductRule.Name = "软件";
121 conductRule.Description = "开启软件所用的8080端口";
122 conductRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT;
123 conductRule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
124 conductRule.Enabled = true;
125 conductRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
126 conductRule.RemotePorts = "8080";
127 firewallPolicy.Rules.Add(stopallRule);
128 firewallPolicy.Rules.Add(qqRule);
129 firewallPolicy.Rules.Add(conductRule);
130 //添加成功,显示成功标志
131 Console.WriteLine("all done");
132 }
133 }
134 static void Main(string[] args)
135 {
136
137 Program p = new Program();
138 string sysversion = p.getsysversion();
139 p.openfire(sysversion);
140 p.handle(sysversion);
141 }
142 }
143 }
代码写的比较急,所以有些地方写的不太好,并且目前所面向的系统主要是win7系统,因此只写了win7的情况(xp的情况与之不同),以后有时间再补齐吧。
文笔不太好,所以基本都是白话,望大家多多包涵,我的初心是大家可以从中学到知识,一起成长!