Thinker

  - long way to go...

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  24 随笔 :: 0 文章 :: 143 评论 :: 0 Trackbacks
最近由于工作和学习需要在家里装上了小区宽带(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   : qujinlong123@gmail.com
  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   : qujinlong123@gmail.com
 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/

posted on 2007-06-20 23:28 Long 阅读(24000) 评论(15)  编辑  收藏 所属分类: Python

评论

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-06-21 10:29 kergee
请问Linux下怎么修改呢  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-06-21 11:16 Zoom.Quiet
咔咔咔,不错!Python 就是用来使用的!
不过GNU/Linux 中就不用这么麻烦了,
一般配置Shell 脚本就足够了,
因为都是纯文本的配置文件,预先组织好,复制一下就好  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-06-21 12:02 笨笨狗
用python操作wim修改,要比这个简单得多……  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-06-21 12:12 Long
@笨笨狗
你说的是WMI?
呵呵,去看一下  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-06-21 12:15 Long
微软官网的脚本中心中有用Windows脚本修改IP的示例,就是使用WMI
大概浏览了一下,看到它写的需要重启电脑,所以就没看了  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-06-21 15:41 Long
@笨笨狗
呵呵,谢谢你的提示,已添加了利用WMI修改IP设置的版本  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-07-02 17:13 zb
Tw的有个人也写一个这样的。easyipconfig.  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2007-07-12 12:15 程鑫
不错,学到知识了   回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2008-01-05 00:03 guest8888
vista下 无法修改成功 是否和权限有关?  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2009-05-13 06:49 网友
@guest8888
同感~  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2009-08-03 14:27 路过
netsh interface ip set address name="本地连接" source=static addr=192.168.1.36 mask=255.255.255.0 gateway=192.168.1.1 gwmetric=auto
echo 更改DNS执行中..

————————————
一句话搞定 不是更简单吗。。  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2010-07-07 16:40 淘宝网
),每次回家和去公司都需要手动改IP,改了几天嫌麻烦就想写个小程序可以自动设置IP,只需要双击一下程序就搞定IP设置  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2012-01-19 20:57 白目
如果能再加入一个GUI用户选择界面就完善了!  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2016-04-12 10:34 guest123
@Long
用wmi修改没有成功,returnValue=(-2147217405,)。请问是什么原因?  回复  更多评论
  

# re: 用Python干实事(一)自动修改Windows的IP、网关和DNS设置 2016-04-12 10:39 guest123
@guest8888
https://msdn.microsoft.com/zh-SG/library/aa389395(v=vs.85)
查了相关文档,returnValue=(-2147217405,)一般是权限或者安全性问题。用管理员身份执行py脚本可以修改成功。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: