修改IP

http://www.blogjava.net/qujinlong123/archive/2007/06/20/125434.html

 

最近由于工作和学习需要在家里装上了小区宽带(80元/月),整个小区共享30M带宽,开始以为会很慢,结果用起来速度还是挺不错的。不说废话了,言归正传,由于家里和公司的IP设置不一样(都是静态的),每次回家和去公司都需要手动改IP,改了几天嫌麻烦就想写个小程序可以自动设置IP,只需要双击一下程序就搞定IP设置。就上网搜了一下,大概有这么几种方法:使用Windows的脚本(http://www.microsoft.com/china/technet/community/scriptcenter/topics/networking/default.mspx)或者编写一个批处理使用netsh命令来完成这个任务,当然用C/C++也是绝对可以的。不过为了练习一下Python和想更多了解一下Python,所以就决定用Python来写个自动设置IP的程序。参考文章:http://www.pconline.com.cn/pcedu/empolder/gj/vc/0508/694212.html
代码如下:

  1  #  FileName: modify_ip.py
  2  #  Author  : qujinlong
  3  #  Email   : [email protected]
  4  #  Date    : 2007-06-20
  5 
  6  import  _winreg
  7 
  8  from  ctypes  import   *
  9 
 10  #  MessageBox = windll.user32.MessageBoxA
 11  #  MessageBox(0, 'Welcome!', 'Hello', 0)
 12 
 13  print   ' 正在修改IP,请稍后 '
 14 
 15  netCfgInstanceID  =  None
 16 
 17  hkey  =  _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, \
 18                         r ' System\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318} ' )
 19 
 20  keyInfo  =  _winreg.QueryInfoKey(hkey)
 21 
 22  #  寻找网卡对应的适配器名称 netCfgInstanceID
 23  for  index  in  range(keyInfo[0]):
 24      hSubKeyName  =  _winreg.EnumKey(hkey, index)
 25      hSubKey  =  _winreg.OpenKey(hkey, hSubKeyName)
 26 
 27       try :
 28          hNdiInfKey  =  _winreg.OpenKey(hSubKey, r ' Ndi\Interfaces ' )
 29          lowerRange  =  _winreg.QueryValueEx(hNdiInfKey,  ' LowerRange ' )
 30 
 31           #  检查是否是以太网
 32           if  lowerRange[0]  ==   ' ethernet ' :
 33              driverDesc  =  _winreg.QueryValueEx(hSubKey,  ' DriverDesc ' )[0]
 34               #  print 'DriverDesc: ', driverDesc
 35              netCfgInstanceID  =  _winreg.QueryValueEx(hSubKey,  ' NetCfgInstanceID ' )[0]
 36               #  print 'NetCfgInstanceID: ', netCfgInstanceID
 37               break
 38 
 39          _winreg.CloseKey(hNdiInfKey)  #  关闭 RegKey
 40       except  WindowsError:
 41           print  r ' Message: No Ndi\Interfaces Key '
 42 
 43       #  循环结束,目前只提供修改一个网卡IP的功能
 44      _winreg.CloseKey(hSubKey)
 45 
 46  _winreg.CloseKey(hkey)
 47 
 48  if  netCfgInstanceID  ==  None:
 49       print   ' 修改IP失败 - 没有找到网络适配器 '     
 50      exit()
 51 
 52  #  print netCfgInstanceID
 53 
 54  #  通过修改注册表设置IP
 55  strKeyName  =   ' System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\ '   +  netCfgInstanceID
 56 
 57  #  print strKeyName
 58 
 59  hkey  =  _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, \
 60                         strKeyName, \
 61                         0, \
 62                         _winreg.KEY_WRITE)
 63 
 64  #  定义需要修改的IP地址、子网掩码、默认网关和DNS等
 65  ipAddress  =  [ ' 192.168.1.135 ' ]
 66  subnetMask  =  [ ' 255.255.255.0 ' ]
 67  gateway  =  [ ' 192.168.1.10 ' ]
 68  dnsServer  =  [ ' 202.106.196.115 ' ' 202.106.0.20 ' ]
 69 
 70  try :
 71      _winreg.SetValueEx(hkey,  ' IPAddress ' , None, _winreg.REG_MULTI_SZ, ipAddress)
 72      _winreg.SetValueEx(hkey,  ' SubnetMask ' , None, _winreg.REG_MULTI_SZ, subnetMask)
 73      _winreg.SetValueEx(hkey,  ' DefaultGateway ' , None, _winreg.REG_MULTI_SZ, gateway)
 74      _winreg.SetValueEx(hkey,  ' NameServer ' , None, _winreg.REG_SZ,  ' , ' .join(dnsServer))
 75  except  WindowsError:
 76       print   ' Set IP Error '
 77      exit()
 78 
 79  _winreg.CloseKey(hkey)
 80 
 81  #  调用DhcpNotifyConfigChange函数通知IP被修改
 82  DhcpNotifyConfigChange  =  windll.dhcpcsvc.DhcpNotifyConfigChange
 83 
 84  inet_addr  =  windll.Ws2_32.inet_addr
 85 
 86  #  DhcpNotifyConfigChange 函数参数列表:
 87  #  LPWSTR lpwszServerName,  本地机器为None
 88  #  LPWSTR lpwszAdapterName, 网络适配器名称
 89  #  BOOL bNewIpAddress,      True表示修改IP
 90  #  DWORD dwIpIndex,         表示修改第几个IP, 从0开始
 91  #  DWORD dwIpAddress,       修改后的IP地址
 92  #  DWORD dwSubNetMask,      修改后的子码掩码
 93  #  int nDhcpAction          对DHCP的操作, 0 - 不修改, 1 - 启用, 2 - 禁用
 94  DhcpNotifyConfigChange(None, \
 95                         netCfgInstanceID, \
 96                         True, \
 97                         0, \
 98                         inet_addr(ipAddress[0]), \
 99                         inet_addr(subnetMask[0]), \
100                         0)
101 
102  print   ' 修改IP结束 '
103 

Python写起来真是清爽啊,没有一点拖泥带水,没有任何的指针、引用传进传出,也不用搞复杂的类型变来变去。
代码中用到了winreg模块去读取和修改Windows的注册表,还用到了ctypes去链接DLL调用Windows API。
至于程序所使用的修改IP的原理在参考文章中描述的很清楚,有什么问题可以mail我。
程序以简单起见,在修改IP的过程中一些例外情况并没有处理,呵呵,只要自己能正常使用就行了:)
等过两天有时间写个界面程序,可以设置和读取IP配置,类似于Windows的网络设置的UI界面。

不喜欢上面代码中有行号的朋友可以下载这个源程序:自动修改IP的Python程序

改进性能从点滴做起:
(1).由于Python中的字符串是不可变的,每次使用“+”号创建新字符串会拷贝原有的字符串构造新的字符串,降低性能,所以应避免使用“+”号构造字符串(类似于Java)。据此可将上面的一句代码更改如下:
strKeyName = r'System\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\%s' % netCfgInstanceID
(2).待续...

(2007-06-21增加)
笨笨狗的提示,研究了一下在Python中使用WMI来实现这个功能,比上面的修改注册表方法简单的太多,而且比使用Windows的脚本也简单了一点。先将新版本的代码贴出来(其中使用了Tim Golden对WMI的包装模块,并且这个模块使用了Python for Windows extensions(pywin32)):

 1  #  -*- coding: cp936 -*-
 2 
 3  #  FileName: modify_ip(wmi).py
 4  #  Author  : qujinlong
 5  #  Email   : [email protected]
 6  #  Date    : 2007-06-21
 7 
 8  import  wmi
 9 
10  print   ' 正在修改IP,请稍后 '
11 
12  wmiService  =  wmi.WMI()
13 
14  colNicConfigs  =  wmiService.Win32_NetworkAdapterConfiguration(IPEnabled  =  True)
15 
16  # for objNicConfig in colNicConfigs:
17  #     print objNicConfig.Index
18  #     print objNicConfig.SettingID
19  #     print objNicConfig.Description
20  #     print objNicConfig.IPAddress
21  #     print objNicConfig.IPSubnet
22  #     print objNicConfig.DefaultIPGateway
23  #     print objNicConfig.DNSServerSearchOrder
24 
25  if  len(colNicConfigs)  <   1 :
26       print   ' 没有找到可用的网络适配器 '
27      exit()
28 
29  #  获取第一个网络适配器的设置
30  objNicConfig  =  colNicConfigs[0]
31 
32  # for method_name in objNicConfig.methods:
33  #    method = getattr(objNicConfig, method_name)
34  #    print method
35 
36  arrIPAddresses  =  [ ' 192.168.1.136 ' ]
37  arrSubnetMasks  =  [ ' 255.255.0.0 ' ]
38  arrDefaultGateways  =  [ ' 192.168.1.1 ' ]
39  arrGatewayCostMetrics  =  [ 1 ]
40  arrDNSServers  =  [ ' 192.168.1.3 ' ' 202.106.46.151 ' ' 202.106.0.20 ' ]
41  intReboot  =  0
42 
43  returnValue  =  objNicConfig.EnableStatic(IPAddress  =  arrIPAddresses, SubnetMask  =  arrSubnetMasks)
44  if  returnValue[0]  ==  0:
45       print   '   成功设置IP '
46  elif  returnValue[0]  ==   1 :
47       print   '   成功设置IP '
48      intReboot  +=   1
49  else :
50       print   ' 修改IP失败(IP设置发生错误) '
51      exit()
52 
53  returnValue  =  objNicConfig.SetGateways(DefaultIPGateway  =  arrDefaultGateways, GatewayCostMetric  =  arrGatewayCostMetrics)
54  if  returnValue[0]  ==  0:
55       print   '   成功设置网关 '
56  elif  returnValue[0]  ==   1 :
57       print   '   成功设置网关 '
58      intReboot  +=   1
59  else :
60       print   ' 修改IP失败(网关设置发生错误) '
61      exit()
62 
63  returnValue  =  objNicConfig.SetDNSServerSearchOrder(DNSServerSearchOrder  =  arrDNSServers)
64  if  returnValue[0]  ==  0:
65       print   '   成功设置DNS '
66  elif  returnValue[0]  ==   1 :
67       print   '   成功设置DNS '
68      intReboot  +=   1
69  else :
70       print   ' 修改IP失败(DNS设置发生错误) '
71      exit()
72 
73  if  intReboot  >  0:
74       print   ' 需要重新启动计算机 '
75  else :
76       print   ''
77       print   '   修改后的配置为: '
78       print   '   IP:  ' ' ' .join(objNicConfig.IPAddress)
79       print   '   掩码: ' ' ' .join(objNicConfig.IPSubnet)
80       print   '   网关: ' ' ' .join(objNicConfig.DefaultIPGateway)
81       print   '   DNS: ' ' ' .join(objNicConfig.DNSServerSearchOrder)
82 
83  print   ' 修改IP结束 '
84 

简单了很多,呵呵
源码下载:modify_ip(wmi).zip

http://www.blogjava.net/qujinlong123/

你可能感兴趣的:(IP)