WSH: MAC- und IP-Adressen

01.09.2006 von Martin Kuppinger
Der zweite Teil der Artikelfolge befasst sich zunächst mit netsh dhcp, einem Befehl, mit dem sich verschiedene Aktivitäten rund um DHCP durchführen lassen. Es werden darüber hinaus Skriptteile vorgestellt, mit denen sich über WMI Informationen zur MAC- und IP-Adresse von definierten Systemen ermitteln lassen.

Im ersten Teil der Serie wurden die – für den gewünschten Zweck der Ermittlung von MACund IP-Adressen – relativ eingeschränkten Möglichkeiten von netsh dhcp als Befehl für die Konfiguration von DHCP-Servern angesprochen. Nachfolgend werden noch ein paar weitere Möglichkeiten vorgestellt, bevor wir auf Code eingehen, der für die Ermittlung von IP- und MACAdressen über VBScript und WMI eingesetzt werden kann.

Ein Beispiel für netsh dhcp

Die nachfolgenden Zeilen zeigen, wie man netsh dhcp für grundlegende Konfigurationsschritte von DHCP-Servern nutzen kann:

netsh dhcp server 192.168.50.10 add scope
192.168.10.0 255.255.255.0 Standardbereich Standardclients
netsh dhcp server 192.168.50.10 scope 192.168.10.0
add iprange 192.168.10.1 192.168.10.254netsh dhcp
server 192.168.50.10 scope 192.168.10.0 add excluderange
192.168.10.1 192.168.10.25
netsh dhcp server 192.168.50.10 scope 192.168.10.0
set optionvalue 003 IPADDRESS 10.1.1.1 10.1.1.2
netsh dhcp server 192.168.50.10 scope 192.168.10.0
set state 1

In der ersten Zeile wird bei einem DHCP-Server ein Bereich hinzugefügt. Hinter add scope folgen als Parameter die IP-Adresse, die Subnetz-Maske, der Name und der Kommentar.

In der folgenden Zeile wird ein IP-Adressbereich hinzugefügt, bevor anschließend eine Ausnahme definiert wird. Die vierte Zeile zeigt, wie man eine Option setzen kann, bevor der Bereich abschließend aktiviert wird.

Für solche Zwecke ist netsh dhcp gut geeignet. Wie im ersten Teil der Serie ausgeführt wurde, fehlen aber die Optionen, um beispielsweise gezielt eine Liste mit Zuordnungen zwischen vergebenen Leases und MAC-Adressen zu erstellen.

Das Scripting: Codebeispiele

Die praktikabelste Lösung für das Auslesen einer größeren Zahl von IP-Adressen ist die Übergabe etwa von Rechnernamen in einer Textdatei. Diese kann als Eingabe für das Skript dienen. Die Grundstruktur für das Auslesen solcher Dateien findet sich in Listing 1.

Listing 1: Das Auslesen von Code (Quelle: Microsoft)
Const ForReading = 1
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile("c:\scripts\systems.txt", ForReading)
i = 0
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
objDictionary.Add i, strNextLine
i = i + 1
Loop
For Each objItem in objDictionary
‘ Verarbeitung
Next

Zunächst wird hier eine Konstante gesetzt, die später gebraucht wird, um eine Datei für den Read-Only Zugriff zu öffnen. Anschließend wird mit

Set objDictionary = CreateObject("Scripting.Dictionary")

ein so genanntes Dictionary-Objekt erstellt. Dabei handelt es sich um eine Liste von nummerierten Elementen, die später einfach wieder aufgerufen werden kann. Faktisch entspricht die Verarbeitung der in einem Array. Mit

Set objFSO = CreateObject("Scripting.FileSystemObject")

wird danach ein Dateisystemobjekt erstellt, über das im nächsten Schritt eine Datei mit der Liste der Eingabewerte geöffnet wird:

Set objTextFile =
objFSO.OpenTextFile("c:\scripts\systems.txt", For-
Reading)

Diese Datei muss nun schrittweise verarbeitet werden. Die Verarbeitung erfolgt in einer Schleife, wobei der Durchlauf bis zum Dateiende erfolgt. Innerhalb der Schleife wird jeweils eine Zeile ausgelesen und in das Dictionary-Objekt geschrieben. Die erste Zeile hat den Wert 0.

i = 0
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
objDictionary.Add i, strNextLine
i = i + 1
Loop

Damit stehen die Eingabewerte zur Verfügung. Die weitere Verarbeitung kann nun in einer Schleife erfolgen, in der die Einträge im Dictionary-Objekt der Reihe nach ausgelesen werden:

For Each objItem in objDictionary
‘ Verarbeitung
Next

Dieses Raster kann für die Verarbeitung aller Eingabedateien verwendet werden, in denen pro Zeile ein Eintrag zu finden ist. Um die weiteren Informationen zu ermitteln, gibt es nun viele Möglichkeiten. Ein Beispiel ist die Abfrage der Konfiguration der Netzwerkadapter eines Systems. Darüber lassen sich sehr viele Informationen ermitteln. Listing 2 beschränkt sich aber auf Kerninformationen rund um DHCP und die gewünschten IP- und MAC-Adressen.

Listing 2: Der Zugriff auf Informationen zu Adaptern (Quelle:
Microsoft)
On Error Resume Next
Set strComputer = objDictionary.Item(objItem)
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" &
strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery ("Select * from Win32_NetworkAdapterConfiguration")
For Each objItem in colItems
Wscript.Echo "Description: " & objItem.Description
Wscript.Echo "DHCP Enabled: " & objItem.DHCPEnabled
Wscript.Echo "DHCP Lease Expires: " & objItem.DHCPLeaseExpires
Wscript.Echo "DHCP Lease Obtained: " & objItem.DHCPLeaseObtained
Wscript.Echo "DHCP Server: " & objItem.DHCPServer
Wscript.Echo "IP Address: " & objItem.IPAddress
Wscript.Echo "IP Enabled: " & objItem.IPEnabled
Wscript.Echo "IP Subnet: " & objItem.IPSubnet
Wscript.Echo "MAC Address: " & objItem.MACAddress
Next

Dieser Code müsste in Listing 1 in die Schleife eingefügt werden. In diesem Fall wird zunächst auf das Objekt zugegriffen. Für den definierten Computer wird über WMI auf Informationen zu den Netzwerkadaptern zugegriffen. Dieser Verarbeitungsschritt muss in einer Schleife erfolgen, weil es mehrere Netzwerkadapter geben kann. Als Informationen werden die Beschreibung des Adapters, diverse DHCP-Konfigurationsinformationen und Daten wie die IP-Adresse ermittelt. Eine Variante dazu zeigt das nachfolgende Listing:

strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=
impersonate}!\\" & strComputer &
"\root\cimv2")
Set IPConfigSet = objWMIService.ExecQuery ("Select *
from Win32_NetworkAdapterConfiguration Where IPEnabled=
TRUE")
For Each IPConfig in IPConfigSet
If Not IsNull(IPConfig.IPAddress) Then
For i=LBound(IPConfig.IPAddress) to
UBound(IPConfig.IPAddress)
WScript.Echo IPConfig.IPAddress(i)
Next
End If
Next

In diesem Beispiel wird ebenfalls über WMI gearbeitet. Es wird aber eine Abfrage verwendet, die Informationen zur Konfiguration ermittelt, die anschließend ausgewertet werden müssen.

Listing 3 schließlich zeigt im Wesentlichen eine schönere Gestaltung der Ausgabe, orientiert sich aber in seiner Grundstruktur an der Vorgehensweise aus Listing 2.

Listing 3: Eine verfeinerte Ausgabe von Informationen (Quelle:
Microsoft)
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colAdapters = objWMIService.ExecQuery _
("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
n = 1
WScript.Echo
For Each objAdapter in colAdapters
WScript.Echo "Network Adapter " & n
WScript.Echo "================="
WScript.Echo " Description: " & objAdapter.Description
WScript.Echo " Physical (MAC) address: " & objAdapter.MACAddress
WScript.Echo " Host name: " & objAdapter.DNSHostName
If Not IsNull(objAdapter.IPAddress) Then
For i = 0 To UBound(objAdapter.IPAddress)
WScript.Echo " IP address: " & objAdapter.IPAddress(i)
Next
End If
If Not IsNull(objAdapter.IPSubnet) Then
For i = 0 To UBound(objAdapter.IPSubnet)
WScript.Echo " Subnet: " & objAdapter.IPSubnet(i)
Next
End If
If Not IsNull(objAdapter.DefaultIPGateway) Then
For i = 0 To UBound(objAdapter.DefaultIPGateway)
WScript.Echo " Default gateway: " & _
objAdapter.DefaultIPGateway(i)
Next
End If
WScript.Echo
WScript.Echo " DNS"
WScript.Echo " ---"
WScript.Echo " DNS servers in search order:"
If Not IsNull(objAdapter.DNSServerSearchOrder) Then
For i = 0 To UBound(objAdapter.DNSServerSearchOrder)
WScript.Echo " " & objAdapter.DNSServerSearchOrder(i)
Next
End If
WScript.Echo " DNS domain: " & objAdapter.DNSDomain
Fortsetzung Listing 3
If Not IsNull(objAdapter.DNSDomainSuffixSearchOrder) Then
For i = 0 To UBound(objAdapter.DNSDomainSuffixSearchOrder)
WScript.Echo " DNS suffix search list: " & _
objAdapter.DNSDomainSuffixSearchOrder(i)
Next
End If
WScript.Echo
WScript.Echo " DHCP"
WScript.Echo " ----"
WScript.Echo " DHCP enabled: " & objAdapter.DHCPEnabled
WScript.Echo " DHCP server: " & objAdapter.DHCPServer
If Not IsNull(objAdapter.DHCPLeaseObtained) Then
utcLeaseObtained = objAdapter.DHCPLeaseObtained
strLeaseObtained = WMIDateStringToDate(utcLeaseObtained)
Else
strLeaseObtained = ""
End If
WScript.Echo " DHCP lease obtained: " & strLeaseObtained
If Not IsNull(objAdapter.DHCPLeaseExpires) Then
utcLeaseExpires = objAdapter.DHCPLeaseExpires
strLeaseExpires = WMIDateStringToDate(utcLeaseExpires)
Else
strLeaseExpires = ""
End If
WScript.Echo " DHCP lease expires: " & strLeaseExpires
WScript.Echo
WScript.Echo " WINS"
WScript.Echo " ----"
WScript.Echo " Primary WINS server: " & objAdapter.WINSPrimaryServer
WScript.Echo " Secondary WINS server: " & objAdapter.WINSSecondaryServer
WScript.Echo
n = n + 1
Next
Function WMIDateStringToDate(utcDate)
WMIDateStringToDate = CDate(Mid(utcDate, 5, 2) & "/" & _
Mid(utcDate, 7, 2) & "/" & _
Left(utcDate, 4) & " " & _
Mid (utcDate, 9, 2) & ":" & _
Mid(utcDate, 11, 2) & ":" & _
Mid(utcDate, 13, 2))
End Function

Dieser Code müsste ebenfalls wieder in Listing 1 eingebunden werden. Die Beispiele machen deutlich, wie relativ einfach es ist, Details zu ermitteln, wenn man erst einmal über eine Liste der zu untersuchende Computernamen verfügt.