• [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的实现吧!



    ///******************************************************
    ///本文作者:凌晨的搜索者
    ///博客地址:http://www.cnblogs.com/uu102
    ///本文属于原创,如果有您需要的内容想要转载,请保留此段签名注释,否则作者将保留追究法律责任的权利。
    ///******************************************************
  • 相关阅读:
    su命令cannot set groups: Operation not permitted的解决方法
    Docker 使用指南 (二)—— 搭建本地仓库
    90后小伙云上打造倾诉社交平台
    一起用HTML5 canvas做一个简单又骚气的粒子引擎
    PCB设计流程
    PCB设计检查
    C语言——输入输出函数
    (1)STM32使用HAL库操作GPIO
    几个输入输出函数的总结
    STM32标准库GPIO操作
  • 原文地址:https://www.cnblogs.com/uu102/p/2679293.html
Copyright © 2020-2023  润新知