[python-win32] detecting windows type
David Fraser
davidf at sjsoft.com
Wed Sep 14 13:28:06 CEST 2005
I wrote a module that has a variety of ways to get a MAC address on
different platorms, it may be useful:
import sys
import os
def rawtohex(raw):
"""converts a raw mac address to hex"""
return ":".join(["%02X" % (ord(ch),) for ch in raw])
def getmacs_netbios():
"""uses netbios to find mac addresses"""
# code ported from "HOWTO: Get the MAC Address for an Ethernet Adapter"
# MS KB ID: Q118623
import netbios
ncb = netbios.NCB()
ncb.Command = netbios.NCBENUM
la_enum = netbios.LANA_ENUM()
ncb.Buffer = la_enum
rc = netbios.Netbios(ncb)
if rc != 0: raise RuntimeError, "Unexpected result %d" % (rc,)
for i in range(la_enum.length):
ncb.Reset()
ncb.Command = netbios.NCBRESET
ncb.Lana_num = ord(la_enum.lana[i])
rc = netbios.Netbios(ncb)
if rc != 0: raise RuntimeError, "Unexpected result %d" % (rc,)
ncb.Reset()
ncb.Command = netbios.NCBASTAT
ncb.Lana_num = ord(la_enum.lana[i])
ncb.Callname = "* "
adapter = netbios.ADAPTER_STATUS()
ncb.Buffer = adapter
netbios.Netbios(ncb)
address = rawtohex(adapter.adapter_address)
yield address
def getmacs_wmi():
"""uses wmi interface to find mac addresses"""
# this uses wmi from http://tgolden.sc.sabren.com/python/wmi.html
# its from the example at
http://tgolden.sc.sabren.com/python/wmi_cookbook.html#ip_addresses
import wmi
c = wmi.WMI ()
for interface in c.Win32_NetworkAdapterConfiguration (IPEnabled=1):
hasip = False
for ipaddress in interface.IPAddress:
if ipaddress: hasip = True
if hasip:
yield interface.MACAddress
def getmacs_ifconfig():
"""parses the output of unix ifconfig to find mac addresses"""
lines = os.popen("ifconfig", "r").readlines()
headerlines = [line for line in lines if line and not
line[:1].isspace()]
for line in headerlines:
parts = line.split()
ifname = parts[0]
if 'HWaddr' in parts:
hwpart = parts.index('HWaddr')
if hwpart+1 < len(parts):
mac = parts[hwpart+1]
yield mac
def getmacs_ipconfig():
"""parses the output of windows ipconfig to find MAC addresses"""
lines = os.popen("ipconfig /all", "r").readlines()
for line in lines:
if line and not line[:1].isspace():
header = line
ipaddress, mac = None, None
elif line.strip():
if line.strip().startswith("IP Address") and ":" in line:
ipaddress = line.split(":", 1)[1].strip()
if mac:
yield mac
ipaddress, mac = None, None
if line.strip().startswith("Physical Address") and ":" in line:
mac = line.split(":", 1)[1].strip()
if ipaddress:
yield mac
ipaddress, mac = None, None
def getmacs_winarp():
"""parses the output of windows arp to find MAC addresses"""
lines = os.popen("arp -a", "r").readlines()
for line in lines:
if line.startswith("Interface"):
header = line
ipaddress, mac = None, None
elif line.strip().startswith("Internet Address"):
pass
elif line.strip():
ipaddress, mac = line.strip().split()[:2]
yield mac
def ipaddr2mac_winarp(ipaddr):
"""uses SendARP and ctypes to convert an IP Address to an ethernet
address"""
# see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/347812
import ctypes
try:
SendARP = ctypes.windll.Iphlpapi.SendARP
except:
raise NotImplementedError('Usage only on Windows 2000 and above')
import struct
ip = ipaddr
if isinstance(ip, (str, unicode)):
ip = [int(i) for i in ip.split(".")]
ip = struct.pack("BBBB", *ip)
ip = struct.unpack("l", ip)[0]
buffer = ctypes.c_buffer(6)
addlen = ctypes.c_ulong(ctypes.sizeof(buffer))
if SendARP(ip, 0, ctypes.byref(buffer), ctypes.byref(addlen)) != 0:
raise WindowsError('Retrieval of mac address(%s) - failed' % ipaddr)
macaddr = rawtohex(struct.unpack('6s', buffer)[0])
return macaddr
def getethdevs_ifconfig():
"""parses the output of ifconfig to get a list of ethernet devices"""
lines = os.popen("ifconfig", "r").readlines()
headerlines = [line for line in lines if line and not
line[:1].isspace()]
for line in headerlines:
parts = line.split()
ifname = parts[0]
yield ifname
def getethdevs_proc():
"""looks at /proc/net/dev to get a list of ethernet devices"""
lines = open("/proc/net/dev").readlines()
for line in lines:
if ":" in line:
ethdev = line.split(":", 1)[0].strip()
yield ethdev
getethdevs = getethdevs_proc
def getmac_socket(ethdev):
"""returns the mac address by opening a socket on the given device.
requires right permissions"""
import socket
s = socket.socket(socket.AF_PACKET,socket.SOCK_RAW)
s.bind((ethdev,9999))
rawmac = s.getsockname()[-1]
return rawtohex(rawmac)
def getmacs_socket():
"""returns the mac address by opening a socket on the devices found
by getethdevs. requires right permissions"""
for ethdev in getethdevs():
mac = getmac_socket(ethdev)
if mac:
yield mac
def getmac_ioctl(ethdev):
"""returns the mac address by using ioctl calls on a socket"""
#
http://groups-beta.google.com/group/comp.lang.python/search?q=fcntl+socket+ifconfig
# look at http://www.webservertalk.com/message891078.html for some C
code
import fcntl
import struct
import socket
ifrn_name = ethdev
ifru_addr_family = socket.AF_INET
ifru_addr_data = ""
ifr = struct.pack("16sH14s", ifrn_name, ifru_addr_family, "")
SIOCGIFADDR = 0x8915
SIOCGIFHWADDR = 0x8927
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sfd = s.fileno()
# get the IP address
try:
ifr_result = fcntl.ioctl(sfd, SIOCGIFADDR, ifr)
ipaddr = struct.unpack("16sHH4B8s", ifr_result)[3:7]
ipaddr = ".".join([str(d) for d in ipaddr])
except IOError:
ipaddr = None
# get the ethernet address
try:
ifr_result = fcntl.ioctl(sfd, SIOCGIFHWADDR, ifr)
ethaddr = struct.unpack("16sH6s8s", ifr_result)[2]
if sum([ord(c) for c in ethaddr]) == 0:
return None
ethaddr = rawtohex(ethaddr)
except IOError:
ethaddr = None
return ethaddr
def getmacs_ioctl():
"""returns the mac address by opening a socket on the devices found
by getethdevs. requires right permissions"""
for ethdev in getethdevs():
mac = getmac_ioctl(ethdev)
if mac:
yield mac
def getmacs():
if sys.platform == 'linux2':
return getmacs_ioctl()
elif sys.platform == 'win32':
return getmacs_winarp()
if __name__ == "__main__":
for address in getmacs():
print address
le dahut wrote:
>Thanks for your advice. A colleague told me how to get those
>informations. First install WMI on the 95/98 station, then write the
>program and compile it with py2exe, then it should work on every 95/98
>station (also where WMI is NOT installed !).
>
>Note that 'ipconfig' is available on win98 so a
>os.popen('ipconfig /all') can be parsed to get infos.
>
>
>K.
>
>Le vendredi 09 septembre 2005 à 10:44 -0700, Tim Roberts a écrit :
>
>
>>On Fri, 09 Sep 2005 09:42:18 +0200, le dahut <le.dahut at laposte.net> wrote:
>>
>>
>>
>>>Maybe I can parse the output of a 'ipfonfig' command,
>>>
>>>
>>>
>>Nope, that won't work. Ipconfig is NT-only. 95 and 98 have winipcfg,
>>but it is a GUI tool, not a command-line tool.
>>
>>
>>
>>>but commands.getoutput only work with unix, not with windows. Is there
>>>another way to get the output of a command line program under windows ?
>>>
>>>
>>>
>>The usual way is to use os.popen, which works everywhere. However, as I
>>said, that won't help you with this information.
>>
>>In fact, it is surprisingly difficult to get information about the
>>network interfaces on a 95/98 machine. Have you tried the downloadable
>>WMI support mentioned earlier?
>>
More information about the Python-win32
mailing list