How to scan ip addresses range and get important details with Powershell GUI - Part 4

Today i would like to announce that finally the powershell script that start before a month has finish.

I could upload the script in Microsoft Technet and just inform you that i have a new script.

But i think that will help you and be more valuable if explain how i have create the script.

So in the future if someone wants can be extend the script base on your requirements.

This is my last article for the specific script but i will proceed with few updates in the future.

I will keep you up to date from my blog, twitter and facebook when upload a new update.

The script you can download from https://gallery.technet.microsoft.com/Scan-Range-of-Ip-Addresses-43f531ac?redir=0

Just to remember you that the first lines are the code for the GUI ( Forms,buttons,datagridview).

If you would like to follow how start and all the changes until here you can read the following articles

How to scan ip addresses range and get important details with Powershell GUI

How to scan ip addresses range and get important details with Powershell GUI - Part 2

How to scan ip addresses range and get important details with Powershell GUI - Part 3

So let's start to explain line by line the changes and the issues that face until the end.

Prerequisites

Before run the script must be follow the prerequisites

  • Wsman must be enable in every PC/Server that will be scan
  • Wsman ports must be open in Firewall

You can find the article How to Manage PC or Servers Remotely with Powershell to help you test wsman and enable it with different ways.

Also to run the script must have enable the WsMan in PC/Servers and allow the 

After that we start with the actions that will happened when click the Scan button

  • First we initiate variables $a & $b which are the Start Ip , End Ip and the $ which is the first 3 parts.
  • We apply in varible $cred the Get-Credentials and last we create an array $arr1 that will use to store the computer names and ip addresses after scan with Foor loop. 

$a=[int]$startip.text
$b=[int]$endip.text
$c=[string]$textbox1.text
$cred = Get-Credential domain\user $arr1=@()

 

Scan range of ip addresses to find computer names and ip addresses

Here we scan the range of ip addresses that give a user to find computer names , ip addresses and store it in an array. The reason is that we want to use Invoke-Command for faster scan. 

Because wit the  Invoke-Commands to scan with ip address need a lot of changes and we don't want this will use the first array to scan computer names and connect in every pc/server with Invoke-Command.

So let's start to explain line by line

  • First create a loop with Foreach to scan the range of ip addresses.
  • I do a check if the ip address is online and a second check if WsMan is enable. 
  • If pass all the checks then create a psobject to add properties of computer name and ip address.
  • If not then base on the check that failed add comments  to explain the reason that failed. 

$a..$b |  ForEach {  $address="$c.$_"
if (Test-Connection -Cn $address -Count 1 -Quiet )
{
try{
if (Test-WSMan -cn $address -ErrorAction Stop{
$o = new-object  psobject
$o | add-member -membertype noteproperty -name ops -value (gwmi Win32_Computersystem -computername $address).Caption | Out-Null
$o | add-member -membertype noteproperty -name ip -value $address | Out-Null}
}
catch
{
$o = new-object  psobject
$o | add-member -membertype noteproperty -name ops -value "Wsman isn't enable"| Out-Null
$o | add-member -membertype noteproperty -name ip -value $address | Out-Null
}
}
 else
 {
$o = new-object  psobject
$o | add-member -membertype noteproperty -name ops -value "Check if Pc/Server is online or firewall block the scan"
$o | add-member -membertype noteproperty -name ip -value $address | Out-Null
}
$arr1 += $o
}
 

Read and scan computer name property from the first array to retrieve details of them

  • After the first check create a new array $result to include the results from the second scan.
  • I use Foreach to create a loop that will read the computer name property from the first array $arr1 and connect in each of them with the Invoke-Command to retrieve the details (ram,cpu,disk c,computername,ipaddress) and store it in the new array $result.
  • Inside the Foreach create a $Scriptblock that the only job is to retrieve details with the Get-Ciminstance and add all the properties in object $r

 

$result=@()
Foreach($pc in $arr1){
$ip=$pc.ops
$Scriptblock= {
$properties=@{
IPAddress=(Get-CIMInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE).IPAddress
Computername=(Get-CIMInstance Win32_ComputerSystem ).Caption
OS=(Get-CIMInstance Win32_Operatingsystem ).Caption
CPU=(Get-CIMInstance Win32_processor ).Caption
TotalPhysicalMemory=(Get-CIMInstance Win32_ComputerSystem).TotalPhysicalMemory 
Disk_C=(Get-CIMInstance Win32_Logicaldisk -filter "deviceid='C:'").Size
}
$r=New-Object psobject -Property $properties
$r
}

  • Because Invoke-Command work in Remote connections the issue that face for days was how to pass the object from the remote connection to local.
  • I resolve the error when add the results from the Invoke-Command in the array $result with the following command.
  • Also i use the Select-Object to exclude the properties PSComputername,RunspaceID which return from the results of the object from the remote connection
  • Last i use Try/Catch to catch the errors when failed to connect. 

Try{
$result+=Invoke-Command  -cn $ip -Credential $cred -ArgumentList $ip -ScriptBlock $Scriptblock -ErrorAction Stop | Select-Object -property
IPAddress,Computername,OS,CPU,TotalPhysicalMemory,Disk_C -ExcludeProperty PSComputername,RunspaceID
}
catch
{
$properties=@{
IPAddress=$pc.ip
Computername=$pc.ops
OS=$pc.ops
CPU=$pc.ops
TotalPhysicalMemory=$pc.ops
Disk_C=$pc.ops
}
$r=New-Object psobject -Property $properties
$result+=$r
}
}

  • The following lines add all the results from the array $result in the Datagridview

$result| Select-Object -property IPAddress,Computername,OS,CPU,TotalPhysicalMemory,HDD -ExcludeProperty PSComputername,RunspaceID
$arrlist=new-object System.Collections.ArrayList
$arrlist.AddRange($result)
$datagridview.DataSource=$arrlist 
$datagridview.AutoResizeColumns()

  • Here we use SaveDialog to give the options in the user where to save the csv file when click in button Export to Csv

$exportbutton.Add_Click({
$OpenFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$OpenFileDialog.filter = "CSV (*.csv)| *.csv"
$OpenFileDialog.ShowDialog() | Out-Null

  • Last lines use to export all the results from DatagridView to Csv file

$datagridview.Rows |
select -expand DataBoundItem |
export-csv $OpenFileDialog.FileName -NoType
})

 

That's it.

Download the script and run it to take the results.

What do you think? It is helpful? Do you get errors? What changes you would like to do?

I'm waiting your feedback to improve the script. 

Where to send your feedback?

You can send me an email at info@askme4tech.com  or do your comments in Twitter or Facebook

I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at info@askme4tech.com.

Tags