actually i want to modify my existing powershell script. at the moment i need to provide a list of machine names. how do i need to modify my script that i dont't need a txt file, but only provide a ip range. and the script shows me which ip/pc names are online etc
$machines = Get-Content -Path "C:\temp\pcnames.txt"
function Get-LoggedOnUser
{
[CmdletBinding()]
param
(
[Parameter()]
[ValidateScript({ Test-Connection -ComputerName $_ -Quiet -Count 1 })]
[ValidateNotNullOrEmpty()]
[string[]]$ComputerName = $env:COMPUTERNAME
)
foreach ($comp in $machines)
{
$output = @{ 'ComputerName' = $comp }
$output.UserName = (Get-WmiObject -Class win32_computersystem -ComputerName $comp).UserName
$output.Info = (Get-CimInstance -Class CIM_ComputerSystem -ComputerName $comp).model
$output.IP = (Get-CimInstance -CimSession $comp -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'").IPAddress[0]
[PSCustomObject]$output
}
}
Get-LoggedOnUser | Out-GridView
CodePudding user response:
You mean something like this?
function Test-IpRange {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[IpAddress]$IpStart,
[Parameter(Mandatory=$true, Position = 1)]
[IpAddress]$IpEnd
)
# calculate the range of IP addresses by converting the IP to decimal format
# avoid using obsolete property ([IpAddress]$IpAddress).Address
[byte[]]$bytes = $IpStart.GetAddressBytes()
[array]::Reverse($bytes)
$startRange = [System.BitConverter]::ToUInt32($bytes, 0)
[byte[]]$bytes = $IpEnd.GetAddressBytes()
[array]::Reverse($bytes)
$endRange = [System.BitConverter]::ToUInt32($bytes, 0)
# swap if startaddress > end address
if ($startRange -gt $endRange) { $startRange,$endRange = $endRange, $startRange }
for($i = $startRange; $i -le $endRange; $i ) {
$adr = ([IPAddress]$i).GetAddressBytes()
[array]::Reverse($adr)
$ipToTest = [IPAddress]::Parse($($adr -join '.')).IPAddressToString
$ping = Test-Connection -ComputerName $ipToTest -Count 1 -Quiet -ErrorAction SilentlyContinue
if ($ping) {
$computerName = (([System.Net.Dns]::GetHostEntry($ipToTest)).Hostname -split '\.')[0]
$computerInfo = Get-CimInstance -Class CIM_ComputerSystem -ComputerName $computerName
$adapterInfo = Get-CimInstance -ComputerName $computerName -Class Win32_NetworkAdapterConfiguration |
Where-Object { $_.IPAddress -contains $ipToTest }
[PsCustomObject]@{
ComputerName = $computerName
IPAddress = $ipToTest
Online = $true
CurrentUser = $computerInfo.UserName
Manufacturer = $computerInfo.Manufacturer
Model = $computerInfo.Model
MACAddress = $adapterInfo.MACAddress
}
}
else {
[PsCustomObject]@{
ComputerName = 'N/A'
IPAddress = $ipToTest
Online = $false
CurrentUser = 'N/A'
Manufacturer = 'N/A'
Model = 'N/A'
MACAddress = 'N/A'
}
}
}
}
Test-IpRange '192.168.0.10' '192.168.0.15' | Format-Table -AutoSize
would return something like
ComputerName IPAddress Online CurrentUser Manufacturer Model MACAddress
------------ --------- ------ ----------- ------------ ----- ----------
PC07 192.168.0.10 True Contoso\chkdsk Some PC maker, Ltd. ABCDE123 01:23:45:67:89:AA
PC03 192.168.0.11 True Contoso\wipedsk Some PC maker, Ltd. FGHIJ789 0A:1B:1C:1D:1E:1F
N/A 192.168.0.12 False N/A N/A N/A N/A
N/A 192.168.0.13 False N/A N/A N/A N/A
N/A 192.168.0.14 False N/A N/A N/A N/A
N/A 192.168.0.15 False N/A N/A N/A N/A
You could replace everything between if ($ping) { .. }
into
Invoke-Command -ComputerName $ipToTest -HideComputerName -ScriptBlock {
# this will now run on the remote computer
$computerInfo = Get-CimInstance -Class CIM_ComputerSystem
$adapterInfo = Get-CimInstance -Class Win32_NetworkAdapterConfiguration |
Where-Object { $_.IPAddress -contains $using:ipToTest }
[PsCustomObject]@{
ComputerName = $env:COMPUTERNAME
IPAddress = $using:ipToTest
Online = $true
CurrentUser = $computerInfo.UserName
Manufacturer = $computerInfo.Manufacturer
Model = $computerInfo.Model
MACAddress = $adapterInfo.MACAddress
}
} | Select-Object * -ExcludeProperty RunspaceId
and by that have the remote computer gather the information rather than your local machine. However, if that would be faster I cannot say/test myself.
Invoke-Command
can also take an array of computernames/IpAddresses in its -ComputerName
parameter and that would probably speed up the script.
Thing is that you then must first get a sub array of pingable IP addresses using Test-Connection
on the whole range and capture which machines can be pinged and which machines failed.
For the pingable machines then use one single Invoke-Command -ComputerName $onlineMachines
and for the failed ones run a separate loop to output the objects with N/A