Wifi断网自动重连

作者:faaronzheng 转载请注明出处!

最近宿舍wifi不知道为什么不稳定,经常电脑会断开连接,需要手动重连。而我又会整夜开着电脑下东西,十分蛋疼。所以我就小小的学以致用一下,写了一个简单地wifi断网自动重连工具,并且可以设置在断网超过一定时间后会自动关机。开发环境为win8+vs2012,亲测win8下可以连接路由器和connectify。连接时请注意正确选择认证方式和加密方式。但是即使配置正确也有一定可能因为路由器问题无法连接。

Wifi断网自动重连_第1张图片

Wifi断网自动重连_第2张图片

这个程序的实现其实很简单,下面是主要代码的实现。

主要用到了wininet.dll、managedwifi.dll、c#操作cmd、c#操作xml文件和多线程的知识。

wininet.dll主要是获得当前网络的连接状态。使用方法如下先导入wininet.dll

        //检测网络状态
        [DllImport("wininet.dll", EntryPoint = "InternetGetConnectedState")]
        public extern static bool InternetGetConnectedState(out int conState, int reder);       //使用时直接调用InternetGetConnectedState(out int conState, int reder)函数。

我的使用是先定义int Desc = 0;

然后判断 if (InternetGetConnectedState(out Desc, 0))       //如果有网络连接会返回true 


managedwifi.dll主要是用来获取所有无线wifi和对特定wifi进行连接。

         #region 枚举所有无线设备接收到的SSID
         public List<WIFISSID> ScanSSID()                    //获取所有可用wifi
        {
            List<WIFISSID> wifiName = new List<WIFISSID>();        //用来保存wifi信息
            WlanClient client = new WlanClient();
            foreach (WlanClient.WlanInterface wlanIface in client.Interfaces)
            {
                Wlan.WlanAvailableNetwork[] networks = wlanIface.GetAvailableNetworkList(0);
                foreach (Wlan.WlanAvailableNetwork network in networks)
                {
                    WIFISSID targetSSID = new WIFISSID();    
                    targetSSID.wlanInterface = wlanIface;
                    targetSSID.wlanSignalQuality = (int)network.wlanSignalQuality;
                    targetSSID.SSID = GetStringForSSID(network.dot11Ssid);                
                    targetSSID.dot11DefaultAuthAlgorithm = network.dot11DefaultAuthAlgorithm.ToString();
                    targetSSID.dot11DefaultCipherAlgorithm = network.dot11DefaultCipherAlgorithm.ToString();
                    wifiName.Add(targetSSID);
                   
                }
            }
            return wifiName;
        } 
        #endregion

        #region 连接到指定的SSID
        public void ConnectToSSID(WIFISSID ssid,Boolean isSave)      //连接指定wifi
        {                    
            string profileXml = string.Format("<?xml version=\"1.0\" encoding=\"US-ASCII\"?> <WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\"><name>{0}</name><SSIDConfig><SSID><name>{0}</name></SSID></SSIDConfig> <connectionType>ESS</connectionType><connectionMode>auto</connectionMode><autoSwitch>false</autoSwitch><MSM><security><authEncryption><authentication>{1}</authentication><encryption>{2}</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>{3}</keyMaterial></sharedKey></security></MSM></WLANProfile>",name,authen,encry, pswd);
            ssid.wlanInterface.SetProfile(Wlan.WlanProfileFlags.AllUser, profileXml, true);
            ssid.wlanInterface.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Any,name);               
            if (isSave)                                             //是否需要保存
            {
                //xml文件操作
                XmlDocument doc = new XmlDocument();
                doc.Load("setting.xml");
                XmlNodeList nodeList = doc.SelectSingleNode("setting").ChildNodes;
                foreach (XmlNode xn in nodeList)
                {
                    XmlElement xe = (XmlElement)xn;
                    if (xe.GetAttribute("ssid").Equals(name))
                    {
                        isAdded = true;
                    }
                }
                if (!isAdded)                                     //是否已经存在                            
                {
                    XmlOP xml = new XmlOP();
                    xml.addXml(name, pswd);                      //将wifi名和密码写入xml文件
                }
            }     
                   
        }
        #endregion


上面这段代码中最重要的是profileXml,不同的网络格式也会不尽相同,具体请参考

http://msdn.microsoft.com/en-us/library/windows/desktop/aa369853%28v=vs.85%29.aspx


c#操作cmd代码,这部分主要是实现关机和取消关机

        #region 调用Cmd  
        public void useCmd(string str)
        {
            System.Diagnostics.Process process = new Process();
            //StartInfo获取或设置要传递给Process的Start方法的属性.为ProcessStartInfo类型
            process.StartInfo.FileName = "cmd.exe";
            //设置UseShellExecute以指定是否使用操作系统外壳程序启动进程
            process.StartInfo.UseShellExecute = false;
            //使进程从文件或其他设备获取输入
            process.StartInfo.RedirectStandardInput = true;
            //向文件或其他设备返回输出
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            //给命令行传入关机命令
            process.StandardInput.WriteLine(str);
            process.StandardInput.WriteLine("exit");
            process.Close();
        }
        #endregion

c#操作xml文件,xml文件主要是用来保存配置信息、wifi名和wifi密码。主要是因为我没用过xml所以就尝试一下。我觉得xml文件像一个树的结构。具体使用可以自行查找资料,还是十分简单的。

以下是我的实现代码.

    #region 创建xml文件
        public void creXml()    
        {
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "gb2312", "yes");
            doc.AppendChild(dec);
            XmlElement elem1 = doc.CreateElement("", "setting", "");
            doc.AppendChild(elem1);
            XmlNode root = doc.SelectSingleNode("setting");
            XmlElement basic = doc.CreateElement("basic");
            basic.SetAttribute("timeout", "10");
            basic.SetAttribute("authen", "WPAPSK");
            basic.SetAttribute("encry", "AES");
            root.AppendChild(basic);           
            doc.Save("setting.xml");
        }
    #endregion


   #region 添加结点到xml
        public void addXml(string SSID,string pswd)   
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("setting.xml");
            XmlNode root = doc.SelectSingleNode("setting");
            XmlElement elem = doc.CreateElement(SSID);
            elem.SetAttribute("ssid", SSID);
            elem.SetAttribute("pswd", pswd);
            root.AppendChild(elem);
            doc.Save("setting.xml");
        }

    #endregion

这个程序也用到了多线程知识。除了主线程外还有重连线程、断网关机线程。

具体实现代码如下

    #region  重连线程
        public void AutoConThread(Boolean isSave)
        {
            int Desc = 0;
            while (true)
            {
                if (InternetGetConnectedState(out Desc, 0))       //有网络连接               
                {
                    sw.Reset();                //重置时间
                    continue;
                }
                else
                {
                    AutoConFlag = true;
                    sw.Start();                //开始计时
                    Thread.Sleep(1000);
                }
                if (AutoConFlag)
                {
                    wifi.ConnectToSSID(targetSSID, isSave);             //连接wifi
                    AutoConFlag = false;
                    Thread.Sleep(60000);
                }

                Thread.Sleep(10000);
            }
        }
     #endregion


    #region 断网关机线程
        public void watchThread()                                        
        {
            while (true)
            {
                if (Convert.ToInt32(sw.ElapsedMilliseconds) > time)
                {
                    timeout = true;
                }
                if (timeout)
                {
                    useCmd("shutdown -s -t 600");
                    timeout = false;
                }
                Thread.Sleep(10000);
 
            }
        }

    #endregion

这些线程都是死循环一直运行的,这样的话启动后即使你关掉程序,但是线程还在继续工作,进程里还能看到程序在跑。一个很好地解决办法就是把这些线程设置为后台线程,这样的话关闭应用程序后线程也会结束。

  autoConnect = new Thread(()=>state.AutoConThread(isSave));
  autoConnect.IsBackground = true;                 //设置线程为后台进程
  //System.Environment.Exit(0); 也可以起到退出后程序完全关闭的效果
  autoConnect.Start();

源代码下载:

http://download.csdn.net/detail/faaronzheng/7250515



发现bug或有好的改进请告诉我,大家共同学习。


你可能感兴趣的:(C#,wifi断网自动重连)