Home ProgrammingPowerShell PowerShell: Enumerate devices on a given subnet

PowerShell: Enumerate devices on a given subnet

by Kliment Andreev
5.8K views

This script enumerates all devices that are accessible on a given subnet and it will dump the output in a CSV file.
If the device is a Windows computer, the script will run several WMI queries, so you’ll know the OS model, the Service Pack level, hardware manufacturer, CPU model and count, RAM, disk, partition sizes etc. If the device is running non-Windows OS, it will use nmap to identify the OS, which means you need nmap installed. Also make sure that nmap can be executed and that the nmap install folder is in your path variable.

Create a folder called c:\scripts\DevicesBySubnet\, place the script there and execute it.

The list of subnets that you need to analyze needs to be in a file called c:\scripts\DevicesBySubnet\subnets.txt.
The format is like this:

192.168.1.0 	255.255.255.0	LOCATION1
172.16.0.0	255.255.0.0 	LOCATION2
10.0.0.0	255.0.0.0	LOCATION3

You can replace LOCATION with whatever string you want. It will be included in the CSV file in a separate column. The module to do the subnet calculation was written by Chris Dent and it can be found here.

Function Get-NetworkRange( [String]$IP, [String]$Mask ) {
If ($IP.Contains("/"))
{
	$Temp = $IP.Split("/")
	$IP = $Temp[0]
	$Mask = $Temp[1]
}

If (!$Mask.Contains("."))
{
	$Mask = ConvertTo-Mask $Mask
}

$DecimalIP = ConvertTo-DecimalIP $IP
$DecimalMask = ConvertTo-DecimalIP $Mask

$Network = $DecimalIP -BAnd $DecimalMask
$Broadcast = $DecimalIP -BOr ((-BNot $DecimalMask) -BAnd [UInt32]::MaxValue)

For ($i = $($Network + 1); $i -lt $Broadcast; $i++) {
	ConvertTo-DottedDecimalIP $i
	}
}

Function ConvertTo-DecimalIP {
<#
	.Synopsis
	Converts a Decimal IP address into a 32-bit unsigned integer.
	.Description
	ConvertTo-DecimalIP takes a decimal IP, uses a shift-like operation on each octet and returns a single UInt32 value.
	.Parameter IPAddress
	An IP Address to convert.
#>
[CmdLetBinding()]
Param(
	[Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
	[Net.IPAddress]$IPAddress
)

Process {
	$i = 3; $DecimalIP = 0;
	$IPAddress.GetAddressBytes() | ForEach-Object { $DecimalIP += $_ * [Math]::Pow(256, $i); $i-- }
	Return [UInt32]$DecimalIP
	}
}

Function ConvertTo-DottedDecimalIP {
<#
	.Synopsis
	Returns a dotted decimal IP address from either an unsigned 32-bit integer or a dotted binary string.
	.Description
	ConvertTo-DottedDecimalIP uses a regular expression match on the input string to convert to an IP address.
	.Parameter IPAddress
	A string representation of an IP address from either UInt32 or dotted binary.
#>
[CmdLetBinding()]
Param(
	[Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
	[String]$IPAddress
)

Process {
	Switch -RegEx ($IPAddress) {
		"([01]{8}\.){3}[01]{8}" {
			Return [String]::Join('.', $( $IPAddress.Split('.') | ForEach-Object { [Convert]::ToUInt32($_, 2) } ))
		}
		"\d" {
			$IPAddress = [UInt32]$IPAddress
			$DottedIP = $( For ($i = 3; $i -gt -1; $i--) {
			$Remainder = $IPAddress % [Math]::Pow(256, $i)
			($IPAddress - $Remainder) / [Math]::Pow(256, $i)
			$IPAddress = $Remainder
		} )
		#Return [String]::Join('.', $DottedIP)
		[String]$strIPAddress = [String]::Join('.', $DottedIP)
		Write-Host $strIPAddress
		$result = Get-WMIObject -query "select StatusCode from Win32_PingStatus where Address = '$strIPAddress'"
		# PING
		if ($result.statuscode -eq 0) {
			#Write-Host $strIPAddress  "RESPOND"
			$Manufacturer = ""; $Model = ""; $RAM = 0; $OS = ""; $SPLevel = ""; $TotalSpace = "";
			$Status=""; $SPLevel = ""; $CPU = ""; $DISK = ""; $Hostname = ""; $FreeSpace = "";
			$colItems = Get-WmiObject Win32_ComputerSystem -Namespace "root\CIMV2" -ComputerName $strIPAddress -ea SilentlyContinue
			if ($?) {
				foreach ($objItem in $colItems) {
					$Manufacturer = $objItem.Manufacturer.Replace(","," ")
					$Model = $objItem.Model.Replace(","," ")
					$RAM = $objItem.TotalPhysicalMemory / 1073741824
					$RAM = [Math]::Round($RAM,2)
				
				}	
				$colItems = Get-WmiObject Win32_OperatingSystem -Namespace "root\CIMV2" -Computername $strIPAddress
				foreach ($objItem in $colItems) {
					$OS = $objItem.Caption.Replace(","," ")
					$SPLevel = $objItem.ServicePackMajorVersion
				}
				$colItems = Get-WmiObject Win32_Processor -Namespace "root\CIMV2" -Computername $strIPAddress
				$i = 0
				foreach($objItem in $colItems) {
    				$CPU = $CPU + $objItem.DeviceID + $objItem.Name + " "
					$CPU = $CPU.Replace(","," ")
					$i = $i + 1
    			}
				$noCPU = $i
				$colItems = Get-WmiObject Win32_DiskDrive -Namespace "root\CIMV2" -ComputerName $strIPAddress
				$i=0
				foreach($objItem in $colItems) {   				
    				$DISK2 = "Disk" + $i + ": " + [Math]::Round(($objItem.Size / 1073741824),2) + " "
					$DISK = $DISK + $DISK2
					$i = $i + 1;
				}
				$colItems = Get-WmiObject Win32_LogicalDisk -Namespace "root\CIMV2" -ComputerName $strIPAddress -Filter "drivetype=3"
				foreach ($objItem in $colItems) {
					$TotalSpace2 = $objItem.Size
					$TotalSpace2 = $TotalSpace2 / 1073741824
					$TotalSpace2 = [Math]::Round($TotalSpace2,2)
					$TotalSpace = $TotalSpace + "Size " + $objItem.Caption + $TotalSpace2 + " "
					$FreeSpace2 = $objItem.FreeSpace
					$FreeSpace2 = $FreeSpace2 / 1073741824
					$FreeSpace2 = [Math]::Round($FreeSpace2,2)
					$FreeSpace = $FreeSpace + "Free " + $objItem.Caption + $FreeSpace2 + " "
					$Hostname = $objItem.SystemName
				}	
				$strWriteLine = ("," + $strIPAddress + "," + $Hostname + "," + $Manufacturer + "," + $Model + "," `
								 + $RAM + "," + $OS + "," + $SPLevel + "," + $noCPU + "," + $DISK `
								 +"," + $TotalSpace +"," + $FreeSpace + ",")
				$stream.WriteLine($strWriteLine)
				break
			}	
			#NMAP
			nmap -O $strIPAddress 2>&1 | out-file gpgout.txt
			$Status = (Get-Content gpgout.txt)[-5 .. -5]
			[String]$Status = $Status
			$stream.WriteLine("," + $strIPAddress + "," + $Status)

		} else {
			#Write-Host $strIPAddress "NOT RESPOND"
			$strWriteLine = ("," + $strIPAddress + ",NO RESPONSE")
			$stream.WriteLine($strWriteLine)
			#Write-Host $strIPAddress			
		}
		}
		default {
			Write-Error "Cannot convert this format"
		}	
	}	
}
}


#Main
$arrSubnets = get-Content -Path "c:\Scripts\DevicesBySubnet\subnets.txt"
$strDate = Get-Date
$strFileName = "C:\Scripts\DevicesBySubnet\" + $strDate.Month + $strDate.Year + ".csv"
$stream = [System.IO.StreamWriter] $strFileName
$strWriteLine = (",IP,Hostname,Manufacturer,Model, RAM, OS, SP, CPU, DISK(GB), Total(GB), Free(GB)")
$stream.WriteLine($strWriteLine)

foreach ($strLine in $arrSubnets){ 
	$strLine = $strLine.split("`t")
	$strIP = $strLine[0]
	$strSubnet = $strLine[1]
	$strLocation = $strLine[2]
	$strWriteLine = ($strIP + "  " + $strLocation)
	$stream.WriteLine($strWriteLine)
	Get-NetworkRange $strIP $strSubnet
}
$stream.close()

Related Articles

Leave a Comment

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More