PowerShell – Workstation NIC Settings

Recently, we found a need to try and figure out why some workstations in a remote office were performing abysmally. The office, located in China, is notorious for some amazingly awful wiring in the office… most of it is actually run through some crummy conduit, encased in the concrete floor. The rest of the wiring is run in the plenum and all signs point to rats being in the area (droppings and damaged other fun “chewed” things).

So, rather than ask everyone to leave their machines turned on over night and remote control them, I thought that a nice WMI script via PowerShell would be in order.

This script actually led to a fairly interesting learning moment about NIC settings in the OS.

So… here’s the script (notice that it is similar to the last script. I like having a framework script to use for these kinds of things):

### # Search through AD for listing of workstations in HKG ### $strWorkstationList = @() # Connect to the Domain at the LDAP location specified $ou = [ADSI]"LDAP://ou=HKG,ou=Workstations,DC=domain,dc=local" # Parse through the objects in the OU location for devices that are described as "computer" ForEach ($child in $ou.psbase.Children) { if ($child.ObjectCategory -like '*computer*') { #Write results to the screen for diagnostic purposes #Write-Host $child.Name #Append the results to the strWorkstation string $strWorkstationList += $child.Name }#end if }#end for each loop ### # Parse through the list of workstations from the OU and look for NIC information from them (they need to be online) ### Write-Host "Begining to parse through the workstation list and locate NIC information" Write-Host $strWorkstationList # Ping the host to ensure that it is available on the network. # NOTE: If the firewall is configured to disallow ICMP, it will appear to be down and not be checked. # NOTE to the NOTE: if the firewall is configured to disallow ICMP, it is likely WMI is disallowed as well. ForEach ($serverName in $strWorkstationList) { try { $ping = new-object System.Net.NetworkInformation.Ping $Reply = $ping.Send($serverName) #Write-Host "Ping to " $serverName " is " $Reply.status if($Reply.status -ne "Success") { Write-Host $serverName " not responding on the network -- Status: " $Reply.status } else { Write-Host $serverName " is responding on the network -- Status: " $Reply.status $Reply.RoundtripTime "ms" Write-Host "Connecting to " $serverName # Connect via WMI to the workstation ('aka - $serverName) $NicConfig = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $serverName -ErrorVariable $exceptionVariable $myCol = @() # Parse through each NIC on the workstation (since they are configured with multiple) ForEach ($Nic in $NicConfig) { # If the NIC has an IP address assigned If ($Nic.IPAddress -ne $null) { # Define the object holding the output per NIC $myObj = "" | Select-Object Description, DHCPEnabled, IPAddress, IPSubnet, DefaultIPGateway, DNSServers, WINSServers, NICModel, SpeedDuplex # Collect values for the NIC $myObj.Description = $Nic.Description $myObj.DHCPEnabled = $Nic.DHCPEnabled $myObj.IPAddress = $Nic.IPAddress $myObj.IPSubnet = $Nic.IPSubnet $myObj.DefaultIPGateway = $Nic.DefaultIPGateway $myObj.DNSServers = $Nic.DNSServerSearchOrder $myObj.WINSServers = $Nic.WINSPrimaryServer,$Nic.WINSSecondaryServer # Connect to the registry on the remote machine in order to determine the duplex status (stored differently depending on NIC manufacturer). # Stored in the registry based on device manufacturer ID $registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $serverName) $baseKey = $registry.OpenSubKey("SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}") $subKeyNames = $baseKey.GetSubKeyNames() ForEach ($subKeyName in $subKeyNames) { $subKey = $baseKey.OpenSubKey("$subKeyName") $ID = $subKey.GetValue("NetCfgInstanceId") If ($ID -eq $Nic.SettingId) { $componentID = $subKey.GetValue("ComponentID") If ($componentID -match "ven_14e4") { $myObj.NICModel = "Broadcom" $requestedMediaType = $subKey.GetValue("RequestedMediaType") $enum = $subKey.OpenSubKey("Ndi\Params\RequestedMediaType\Enum") $myObj.SpeedDuplex = $enum.GetValue("$requestedMediaType") } ElseIf ($componentID -match "ven_8086") { $myObj.NICModel = "Intel" $SD = $subKey.GetValue("SpeedDuplex") $enum = $subKey.OpenSubKey("Ndi\Params\SpeedDuplex\Enum") $myObj.SpeedDuplex = $enum.GetValue("$SD") } ElseIf ($componentID -match "b06bdrv") { $myObj.NICModel = "HP" $SD = $subKey.GetValue("req_medium") $enum = $subKey.OpenSubKey("Ndi\Params\req_medium\Enum") $myObj.SpeedDuplex = $enum.GetValue("$SD") } Else { $myObj.NICModel = "unknown" $myObj.SpeedDuplex = "unknown" } } } $myCol += $myObj } } $myCol }# End if(workstation successfully pings test) } # End try catch [SystemException] { $var += 1 }# End Catch [DotNetMethodException} } #End ForEach ($serverName in $strWorkstation) Write-Host "Completed parsing through the workstation list and locating NIC information"

The NIC guts of this script is thanks to: http://www.peetersonline.nl/index.php/powershell/gather-nic-properties-including-speed-and-duplex/#more-51

The learning part (in addition to some more WMI and PowerShell scripting) dealt specifically with where the settings for the NICs could be found. I guess I never realized that the settings would be kept with each vendor’s registry location on the server. I guess I thought, perhaps a little naively, that there would be a registry section for the defined interface that contained this information. So, that would explain the “ForEach” logic in the heart of the script that looks for the NICModel, opens a specific registry location, and pulls the results from there. Good times!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s