[c#] 協議模擬編程之ADSL模式下IP自動換


   在編寫一些自動發貼機之類的小軟件時,經常會用到自動更換IP的地方,手動切換的話太麻煩了,因此我們總會相當用腳本或自動化程序來代替手工切換ip的活。如果家里連的是“寬帶連接”,幾句命令就可以自動切換了。

set WShell=createobject("WScript.Shell")
WShell.run "RasDial 寬帶連接 /Disconnect",vbhide,true
WShell.run "RasDial 寬帶連接 用戶名 密碼",vbhide,true


注意保存為Vbs腳本,如上圖。這是很簡單的腳本完成的功能,它可以隱藏運行。

下面我們還是說說用C#的代碼完成IP自動切換,畢竟很多程序如果手動去切換IP會很不協調,程序會運行出錯。

要將已經存在的ADSL寬帶連接從連接狀態斷開,然后再連接,從而強制重新自動分配IP,從而改變IP,完成一系列這樣的功能,除了顯式調用上述代碼中的“RasDial.exe”之外,在網上還可以引用System32目錄下的“rasapi32.dll”,以及" Wininet.dll ”一種方法。

下面是具體步驟:

1.引用命名空間:

using System.Runtime.InteropServices;

接下來就是調用Wininet.dll的API函數,用於寬帶網絡撥號

[System.Runtime.InteropServices.DllImport("Wininet.dll")]
      public  static extern Int32 InternetDial(IntPtr hwndParent, string lpszConnectoid, Int32 dwFlags, ref Int32 lpdwConnection, Int32 dwReserved);
      

順帶申明一下這個函數所引用的類型,這些類型都是直接從Pinvoke.net查找並復制過來的,用於填補InternetDial的參數dwFlags,INTERNET_DIAL_SHOW_OFFLINE是手動撥號(將“取消”按鈕替換為“脫機工作”按鈕),INTERNET_DIAL_FORCE_PROMPT是系統提示下的手動撥號, INTERNET_DIAL_UNATTENDED是自動撥號。

[Flags]
     public enum InternetDialFlags
      {
          INTERNET_DIAL_FORCE_PROMPT = 0x2000,
          INTERNET_DIAL_SHOW_OFFLINE = 0x4000,
          INTERNET_DIAL_UNATTENDED = 0x8000
      }

 這樣一來,我們就可以直接調用這樣一句函數用於連接網絡了。

 int temp = 0;
         Adsl.InternetDial(IntPtr.Zero, "", (int)Adsl.InternetDialFlags.INTERNET_DIAL_UNATTENDED, ref temp, 0);

接下來斷開網絡就稍微"復雜"一點了,先讓我們引用RasHangUp這樣一個API32函數。這里順便將RasHangUp需要用的參數類型和結構都直接申明在里面了。

View Code
 1  public const int RAS_MaxDeviceType = 16;
 2       public const int RAS_MaxDeviceName = 128;
 3       public const int MAX_PATH = 260;
 4       public const int ERROR_BUFFER_TOO_SMALL = 603;
 5       public const int ERROR_SUCCESS = 0;
 6 
 7         [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)]
 8          public struct RASCONN
 9 {
10     public int dwSize;
11     public IntPtr hrasconn;
12     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName)]
13     public string szEntryName;
14     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxDeviceType)]
15     public string szDeviceType;
16     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxDeviceName)]
17     public string szDeviceName;
18     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
19     public string szPhonebook;
20     public int dwSubEntry;
21     public Guid guidEntry;
22     public int dwFlags;
23     public Guid luid;                                                    
24 }
25         [DllImport("rasapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
26         public static extern int RasEnumConnections(
27             [In, Out] RASCONN[] rasconn,
28             [In, Out] ref int cb,
29             [Out] out int connections);
30       public const int RAS_MaxEntryName = 256;
31        //掛斷撥號,斷開網絡鏈接
32       [DllImport("rasapi32.dll", SetLastError = true)]
33      public static extern uint RasHangUp(IntPtr hRasConn);
34      

函數部分就完成了,接下來我們可以這樣寫:

View Code
 1  public void DisConnect()
 2       {
 3            System.Adsl.RASCONN[] connections = new System.Adsl.RASCONN[1];//創建新連接
 4           connections[0].dwSize = Marshal.SizeOf(typeof(System.Adsl.RASCONN)); //未連接申請內存空間
 5           int connectionCount = 0;//設置連接數
 6           int cb = Marshal.SizeOf(typeof(System.Adsl.RASCONN));//
 7           int ret = Adsl.RasEnumConnections(connections, ref cb, out connectionCount);
 8            Adsl.RasHangUp(connections[0].hrasconn);
 9              
10       }

代碼實在是很簡單,一看就明白,因此沒必要多啰嗦了,相信各位比我還在行。這個也就是很久以前就流行於網絡的方法了。但是這樣一個方法其實並不是總能兼容地跑在我們各種各樣的機器上,很多電腦和網絡環境其實都無法真正實現。

在這里干脆給大家添上上述功能實現的完整代碼吧,以免被我說得思路更加不清晰了。^.^

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Runtime.InteropServices;
  6 
  7 namespace System
  8 {
  9     /// <summary>
 10     /// http://www.cnblogs.com/uu102
 11     /// 凌晨的搜索者
 12     /// </summary>
 13    public class Adsl
 14     {
 15       public const int RAS_MaxDeviceType = 16;
 16       public const int RAS_MaxDeviceName = 128;
 17       public const int MAX_PATH = 260;
 18       public const int ERROR_BUFFER_TOO_SMALL = 603;
 19       public const int ERROR_SUCCESS = 0;
 20 
 21         [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)]
 22          public struct RASCONN
 23 {
 24     public int dwSize;
 25     public IntPtr hrasconn;
 26     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName)]
 27     public string szEntryName;
 28     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxDeviceType)]
 29     public string szDeviceType;
 30     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxDeviceName)]
 31     public string szDeviceName;
 32     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
 33     public string szPhonebook;
 34     public int dwSubEntry;
 35     public Guid guidEntry;
 36     public int dwFlags;
 37     public Guid luid;                                                    
 38 }
 39         [DllImport("rasapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 40         public static extern int RasEnumConnections(
 41             [In, Out] RASCONN[] rasconn,
 42             [In, Out] ref int cb,
 43             [Out] out int connections);
 44       public const int RAS_MaxEntryName = 256;
 45        //掛斷撥號,斷開網絡鏈接
 46       [DllImport("rasapi32.dll", SetLastError = true)]
 47      public static extern uint RasHangUp(IntPtr hRasConn);
 48      
 49       [Flags]
 50      public enum InternetDialFlags
 51       {
 52           INTERNET_DIAL_FORCE_PROMPT = 0x2000,
 53           INTERNET_DIAL_SHOW_OFFLINE = 0x4000,
 54           INTERNET_DIAL_UNATTENDED = 0x8000
 55       }
 56       [System.Runtime.InteropServices.DllImport("Wininet.dll")]
 57       public  static extern Int32 InternetDial(IntPtr hwndParent, string lpszConnectoid, Int32 dwFlags, ref Int32 lpdwConnection, Int32 dwReserved);
 58       public void DisConnect()
 59       {
 60            System.Adsl.RASCONN[] connections = new System.Adsl.RASCONN[1];//創建新連接
 61           connections[0].dwSize = Marshal.SizeOf(typeof(System.Adsl.RASCONN)); //未連接申請內存空間
 62           int connectionCount = 0;//設置連接數
 63           int cb = Marshal.SizeOf(typeof(System.Adsl.RASCONN));//
 64           int ret = Adsl.RasEnumConnections(connections, ref cb, out connectionCount);
 65            Adsl.RasHangUp(connections[0].hrasconn);
 66              
 67       }
 68       public string AdslName { get; set; }
 69       public string Uid { get; set; }
 70       public string Pwd { get; set; }
 71       public Adsl(string adslName, string uid, string pwd)
 72       {
 73           this.AdslName = adslName;
 74           this.Uid = uid;
 75           this.Pwd = pwd;
 76 
 77       }
 78       public System.Diagnostics.Process Connect()
 79       {
 80           /* int temp = 0;
 81          Adsl.InternetDial(IntPtr.Zero, "", (int)Adsl.InternetDialFlags.INTERNET_DIAL_UNATTENDED, ref temp, 0);*/
 82           System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
 83           startInfo.FileName = "RasDial";
 84           if (string.IsNullOrEmpty(this.AdslName)) this.AdslName= "寬帶連接";
 85           startInfo.Arguments = string.Format("{0} {1} {2}",this.AdslName,this.Uid,this.Pwd);
 86           startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
 87           System.Diagnostics.Process process = System.Diagnostics.Process.Start(startInfo);
 88           return process;
 89       }
 90       public System.Diagnostics.Process ReDial()
 91       {
 92           DisConnect();
 93          return  Connect();
 94       }
 95      public static System.Diagnostics.Process ClearCookies(string cmd)
 96       {
 97           System.Diagnostics.Process p = new System.Diagnostics.Process();
 98           p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
 99           p.StartInfo.FileName = "RunDll32.exe";
100           // 關閉Shell的使用
101           p.StartInfo.UseShellExecute = false;
102           // 重定向標准輸入
103           p.StartInfo.RedirectStandardInput = true;
104           // 重定向標准輸出
105           p.StartInfo.RedirectStandardOutput = true;
106           //重定向錯誤輸出
107           p.StartInfo.RedirectStandardError = true;
108           p.StartInfo.CreateNoWindow = true;
109 
110           p.Start();
111           p.StandardInput.WriteLine(cmd);
112           p.StandardInput.WriteLine("exit");
113           return p;
114       }
115 
116 
117 
118 
119     }
120  
121 }
122  

以上所述是PPPOE下連接方法,如果是路由器下的連接,則有很大不同,由於時間關系,下次再補充說說 路由器下自動更換IP的實現吧!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM