用DotRas来连接VPN网络

时间:2023-03-08 21:43:07

  最近要用程序来不断的连接VPN(为什么要这样就不讨论了),开始用的是如下代码:

    public static bool ADSL()
         {
             bool flag = true;
             do
             {
                 Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm") + " 重新拨号...");
                 Disconnect(ConfigurationManager.AppSettings["AdslName"]);
                 Thread.Sleep();
                 Connect(ConfigurationManager.AppSettings["AdslName"], ConfigurationManager.AppSettings["Adsl"], ConfigurationManager.AppSettings["Pwd"]);
                 Thread.Sleep();
                 flag = PingIpOrDomainName("www.baidu.com");
             } while (!flag);
             return flag;
         }
         public static bool PingIpOrDomainName(string strIpOrDName)
         {
             try
             {
                 Ping objPingSender = new Ping();
                 PingOptions objPinOptions = new PingOptions();
                 objPinOptions.DontFragment = true;
                 string data = "";
                 byte[] buffer = Encoding.UTF8.GetBytes(data);
                 ;
                 PingReply objPinReply = objPingSender.Send(strIpOrDName, intTimeout, buffer, objPinOptions);
                 string strInfo = objPinReply.Status.ToString();
                 if (strInfo == "Success")
                 {
                     return true;
                 }
                 else
                 {
                     return false;
                 }
             }
             catch (Exception)
             {
                 return false;
             }
         }
         public static string InvokeCmd(string cmdArgs)
         {
             Process p = new Process();
             p.StartInfo.FileName = "cmd.exe";
             p.StartInfo.UseShellExecute = false;
             p.StartInfo.RedirectStandardInput = true;
             p.StartInfo.RedirectStandardOutput = true;
             p.StartInfo.RedirectStandardError = true;
             p.StartInfo.CreateNoWindow = true;
             p.Start();
             p.StandardInput.WriteLine(cmdArgs);
             p.StandardInput.WriteLine("exit");
             return p.StandardOutput.ReadToEnd();
         }
         public static void Connect(string connectionName, string user, string pass)
         {
             string arg = string.Format("rasdial \"{0}\" {1} {2}", connectionName, user, pass);
             InvokeCmd(arg);
         }
         public static void Disconnect(string connectionName)
         {
             string arg = string.Format("rasdial \"{0}\" /disconnect", connectionName);
             InvokeCmd(arg);
         }

  这个类在平时也是能用,问题就在我需要不断的循环(连接-执行业务-断开-连接-执行业务-断开),而且频率还很高。在连接以后ping下baidu.com是否连接成功!但很多次都提示ping不上baidu.com,平时用的时候ping不上,就重新连接,倒也是可以的。

  但最近需要连VPN,决定重新写这些方法,在网上啪啦啪啦好久,用上了DotRas:http://dotras.codeplex.com/

  并且根据Demo,写了个辅助类DialerHelper:

     public class DialerHelper
     {
         public RasHandle handle { get; set; }
         public string VPNIP { get; set; }
         // VPN名称
         public string EntryName { get; set; }
         // VPN用户名
         public string UserName { get; set; }
         // VPN密码
         public string PassWord { get; set; }
         private RasPhoneBook _phoneBook;

         public RasPhoneBook PhoneBook
         {
             get
             {
                 if (_phoneBook == null)
                     _phoneBook = new RasPhoneBook();
                 return _phoneBook;
             }
             set { _phoneBook = value; }
         }
         private RasDialer _dialer;
         public RasDialer Dialer
         {
             get
             {
                 if (_dialer == null)
                     _dialer = new RasDialer();
                 return _dialer;
             }
             set { _dialer = value; }
         }

         public DialerHelper()
         {
         }

         /// <summary>
         /// 带参构造函数
         /// </summary>
         /// <param name="_vpnIP"></param>
         /// <param name="_vpnName"></param>
         /// <param name="_userName"></param>
         /// <param name="_passWord"></param>
         public DialerHelper(string _vpnIP, string _entryName, string _userName, string _passWord)
         {
             this.VPNIP = _vpnIP;
             this.EntryName = _entryName;
             this.UserName = _userName;
             this.PassWord = _passWord;
         }

         /// <summary>
         /// 创建VPN
         /// </summary>
         public void CreateEntry()
         {
             CreateEntry(this.EntryName, VPNIP);
         }
         /// <summary>
         /// 创建VPN
         /// </summary>
         /// <param name="VPNName"></param>
         /// <param name="VPNIP"></param>
         public void CreateEntry(string VPNName,string VPNIP)
         {
             // This opens the phonebook so it can be used. Different overloads here will determine where the phonebook is opened/created.
             this.PhoneBook.Open();

             // Create the entry that will be used by the dialer to dial the connection. Entries can be created manually, however the static methods on
             // the RasEntry class shown below contain default information matching that what is set by Windows for each platform.
             RasEntry entry = RasEntry.CreateVpnEntry(VPNName, IPAddress.Loopback.ToString(), RasVpnStrategy.Default,
                 RasDevice.GetDeviceByName("(PPTP)", RasDeviceType.Vpn));

             entry.PhoneNumber = VPNIP;

             // Add the new entry to the phone book.
             this.PhoneBook.Entries.Add(entry);

         }

         /// <summary>
         /// 连接
         /// </summary>
         public bool ConnectEntry()
         {
             return ConnectEntry(UserName, PassWord);
         }
         /// <summary>
         /// 连接
         /// </summary>
         /// <param name="sender">The object that raised the event.</param>
         /// <param name="e">An <see cref="System.EventArgs"/> containing event data.</param>
         private bool ConnectEntry(string _userName, string _passWord)
         {

             // This button will be used to dial the connection.
             this.Dialer.EntryName = EntryName;
             this.Dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);

             try
             {
                 // Set the credentials the dialer should use.
                 this.Dialer.Credentials = new NetworkCredential(UserName, PassWord);

                 // NOTE: The entry MUST be in the phone book before the connection can be dialed.
                 // Begin dialing the connection; this will raise events from the dialer instance.
                  handle = this.Dialer.Dial();
                  return true;
             }
             catch (Exception ex)
             {
                 return false;
                 //this.StatusTextBox.AppendText(ex.ToString());
             }
         }

         /// <summary>
         /// 连接
         /// </summary>
         public void ConnectEntryAsync()
         {
             ConnectEntryAsync(UserName, PassWord);
         }
         /// <summary>
         /// 连接
         /// </summary>
         /// <param name="sender">The object that raised the event.</param>
         /// <param name="e">An <see cref="System.EventArgs"/> containing event data.</param>
         private void ConnectEntryAsync(string _userName, string _passWord)
         {

             // This button will be used to dial the connection.
             this.Dialer.EntryName = EntryName;
             this.Dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);

             try
             {
                 // Set the credentials the dialer should use.
                 this.Dialer.Credentials = new NetworkCredential(UserName, PassWord);

                 // NOTE: The entry MUST be in the phone book before the connection can be dialed.
                 // Begin dialing the connection; this will raise events from the dialer instance.
                 handle = this.Dialer.DialAsync();
             }
             catch (Exception ex)
             {
                 //this.StatusTextBox.AppendText(ex.ToString());
             }
         }
         /// <summary>
         ///
         /// </summary>
         public void DisconnectEntry()
         {
             if (this.Dialer.IsBusy)
             {
                 // The connection attempt has not been completed, cancel the attempt.
                 this.Dialer.DialAsyncCancel();
             }
             else
             {
                 // The connection attempt has completed, attempt to find the connection in the active connections.
                 RasConnection connection = RasConnection.GetActiveConnectionByHandle(this.handle);
                 if (connection != null)
                 {
                     // The connection has been found, disconnect it.
                     connection.HangUp();
                 }
             }
         }
     }