7.6 KiB
关于 Python 的更多 Windows 系统信息
原文:https://www.blog.pythonlibrary.org/2010/02/06/more-windows-system-information-with-python/
上个月我写了一篇关于获取 Windows 系统信息的文章,我在我的一条评论中提到有另一个脚本可以做这些事情,但是我找不到它。嗯,今天我去挖掘了一下,找到了我想要的剧本。因此,我们要回到兔子洞去寻找更多的技巧和窍门,以便使用 Python 获得关于 Windows 奇妙世界的信息。
以下脚本摘自我在职时使用和维护的登录脚本。我们通常需要几种方法来识别特定用户的机器。幸运的是,大多数工作站都有几个唯一的标识符,比如 IP、MAC 地址和工作站名称(尽管这些都不一定是唯一的...例如,我们实际上有一个工作站,它的网卡与我们的一台服务器的 MAC 相同。不管怎样,让我们来看看代码吧!
如何获得您工作站的名称
在本节中,我们将使用平台模块来获取我们计算机的名称。在我之前的文章中,我们实际上提到了这个技巧,但是因为我们在下一个片段中需要这个信息,所以我将在这里重复这个技巧:
from platform import node
computer_name = node()
一点也不痛苦,对吧?只有两行代码,我们得到了我们需要的。但是实际上至少还有一种方法可以得到它:
import socket
computer_name = socket.gethostname()
这个片段也非常简单,尽管第一个片段稍微短一些。我们所要做的就是导入内置的 socket 模块,并调用它的 gethostname 方法。现在我们已经准备好获取我们电脑的 IP 地址了。
如何用 Python 获取你的 PC 的 IP 地址
我们可以使用上面收集的信息来获取我们电脑的 IP 地址:
import socket
ip_address = socket.gethostbyname(computer_name)
# or we could do this:
ip_address2 = socket.gethostbyname(socket.gethostname())
在这个例子中,我们再次使用了 socket 模块,但是这次我们使用了它的 gethostbyname 方法并传入了 PC 的名称。然后插座模块将返回 IP 地址。
也可以用蒂姆·戈登的T2 的【WMI】模块。下面的例子来自他精彩的 WMI 烹饪书:
import wmi
c = wmi.WMI ()
for interface in c.Win32_NetworkAdapterConfiguration (IPEnabled=1):
print interface.Description
for ip_address in interface.IPAddress:
print ip_address
print
它所做的只是遍历已安装的网络适配器,并打印出它们各自的描述和 IP 地址。
如何用 Python 获取 MAC 地址
现在我们可以将注意力转向获取 MAC 地址。我们将研究两种不同的方法来获得它,从 ActiveState 方法开始:
def get_macaddress(host='localhost'):
""" Returns the MAC address of a network host, requires >= WIN2K. """
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/347812
import ctypes
import socket
import struct
# Check for api availability
try:
SendARP = ctypes.windll.Iphlpapi.SendARP
except:
raise NotImplementedError('Usage only on Windows 2000 and above')
# Doesn't work with loopbacks, but let's try and help.
if host == '127.0.0.1' or host.lower() == 'localhost':
host = socket.gethostname()
# gethostbyname blocks, so use it wisely.
try:
inetaddr = ctypes.windll.wsock32.inet_addr(host)
if inetaddr in (0, -1):
raise Exception
except:
hostip = socket.gethostbyname(host)
inetaddr = ctypes.windll.wsock32.inet_addr(hostip)
buffer = ctypes.c_buffer(6)
addlen = ctypes.c_ulong(ctypes.sizeof(buffer))
if SendARP(inetaddr, 0, ctypes.byref(buffer), ctypes.byref(addlen)) != 0:
raise WindowsError('Retreival of mac address(%s) - failed' % host)
# Convert binary data into a string.
macaddr = ''
for intval in struct.unpack('BBBBBB', buffer):
if intval > 15:
replacestr = '0x'
else:
replacestr = 'x'
if macaddr != '':
macaddr = ':'.join([macaddr, hex(intval).replace(replacestr, '')])
else:
macaddr = ''.join([macaddr, hex(intval).replace(replacestr, '')])
return macaddr.upper()
由于上面的代码不是我写的,所以就不深入了。然而,我的理解是,这个脚本首先检查它是否可以执行 ARP 请求,这仅在 Windows 2000 和更高版本上可用。一旦得到确认,它就会尝试使用 ctypes 模块来获取 inet 地址。完成之后,它会通过一些我不太理解的东西来建立 MAC 地址。
当我第一次开始维护这段代码时,我认为一定有更好的方法来获取 MAC 地址。我想也许 Tim Golden 的 WMI 模块或者 PyWin32 包会是答案。我很确定他给了我下面的片段,或者我是在 Python 邮件列表档案中找到的:
def getMAC_wmi():
"""uses wmi interface to find MAC address"""
interfaces = []
import wmi
c = wmi.WMI ()
for interface in c.Win32_NetworkAdapterConfiguration (IPEnabled=1):
if interface.DNSDomain == 'www.myDomain.com':
return interface.MACAddress
不幸的是,虽然这种方法有效,但它明显降低了登录脚本的速度,所以我最终还是使用了原来的方法。我想 Golden 先生已经发布了一个较新版本的 wmi 模块,所以现在可能更快了。
如何获得用户名
用 Python 获取当前用户的登录名很简单。你所需要的就是 PyWin32 包。
from win32api import GetUserName
userid = GetUserName()
一次快速导入,我们就有了两行代码的用户名。
如何找到用户所在的组
我们可以使用上面获得的 userid 来找出它属于哪个组。
import os
from win32api import GetUserName
from win32com.client import GetObject
def _GetGroups(user):
"""Returns a list of the groups that 'user' belongs to."""
groups = []
for group in user.Groups ():
groups.append (group.Name)
return groups
userid = GetUserName()
pdcName = os.getenv('dcName', 'primaryDomainController')
try:
user = GetObject("WinNT://%s/%s,user" % (pdcName, userid))
fullName = user.FullName
myGroups = _GetGroups(user)
except Exception, e:
try:
from win32net import NetUserGetGroups,NetUserGetInfo
myGroups = []
groups = NetUserGetGroups(pdcName,userid)
userInfo = NetUserGetInfo(pdcName,userid,2)
fullName = userInfo['full_name']
for g in groups:
myGroups.append(g[0])
except Exception, e:
fullname = "Unknown"
myGroups = []
这比我们之前看到的任何一个脚本都要吓人,但实际上非常容易理解。首先,我们导入我们需要的模块或方法。接下来我们有一个简单的函数,它将一个用户对象作为唯一的参数。该函数将遍历该用户的组,并将它们添加到一个列表中,然后返回给调用者。难题的下一部分是获得主域控制器,我们使用 os 模块来完成。
我们将 pdcName 和 userid 传递给 GetObject(它是 win32com 模块的一部分)来获取我们的用户对象。如果工作正常,那么我们可以获得用户的全名和组。如果它失败了,那么我们捕获错误,并尝试从 win32net 模块中获取一些函数信息。如果这也失败了,那么我们就设置一些默认值。
包扎
希望你已经学到了一些有价值的技巧,可以用在你自己的代码中。我已经在 Python 2.4+中使用这些脚本好几年了,它们工作得非常好!