Reputation: 159
I need to scan my network for specific processes on servers. I've done this script:
28..31 | ForEach-Object { Get-Process -ComputerName "192.168.0.$_" -Name svc* }
Now how can I format output so it shows on which IP address found process shown? Thank you.
Upvotes: 1
Views: 158
Reputation: 437813
I suggest switching to PowerShell's remoting, because:
it provides a framework for executing any command remotely - rather than relying on individual cmdlets to support a -ComputerName
parameter and uses a firewall-friendly transport.
it will continue to be supported in PowerShell [Core] v6+, where the cmdlet-individual -ComputerName
parameters aren't supported anymore; this obsolete remoting method uses an older, less firewall-friendly form of remoting that the - obsolete since v3 - WMI cmdlets also use (the latter were replaced by the CIM cmdlets).
It is therefore better to consistently use the firewall-friendly PowerShell remoting with its generic remoting commands (Invoke-Command
, Enter-PSSession
, ...).
If you use Invoke-Command
to target (multiple) remote computers, the objects returned automatically contain and display the name of the originating computer, via the automatically added .PSComputerName
property:
# Create the array of IP addresses to target:
$ips = 28..31 -replace '^', '192.168.0.'
# Use a *single* Invoke-Command call to target *all* computers at once.
# Note: The results will typically *not* reflect the input order of
# given IPs / computer names.
Invoke-Command -ComputerName $ips { Get-Process -Name svc* }
You'll see output such as the following - note the PSComputerName
column:
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName PSComputerName
------- ------ ----- ----- ------ -- -- ----------- --------------
1013 18 7464 13732 52.72 8 0 svchost 192.168.0.30
...
Note that you can suppress automatic display of the .PSComputerName
property with Invoke-Command
's -HideComputerName
parameter.
However, the property is still available programmatically, which allows you to do the following:
Invoke-Command -ComputerName $ips { Get-Process -Name svc* } -HideComputerName |
Format-Table -GroupBy PSComputerName
This yields display output grouped by computer name / IP:
PSComputerName: 192.168.0.30
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
1013 18 7464 13732 52.72 8 0 svchost
...
PSComputerName: 192.168.0.28
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
1007 17 7112 12632 65.45 11 0 svchost
...
If you wanted to sort by IP address before grouping, you could insert | Sort-Object { [version] $_.PSComputerName }
[1] before the Format-Table
call.
For sorting by computer names, just
| Sort-Object PSComputerName
would do.
[1] Casting to [version]
is a trick to ensure proper sorting of IP addresses; IP address strings can be interpreted as [version]
(System.Version
) instances, and such instances are directly comparable, using the numeric values of the version components (first by .MajorVersion
, then by .MinorVersion
, ...)
Upvotes: 3
Reputation: 7479
here's one way to do the job. [grin] what it does ...
Get-Process
cmdlet will NOT accept an ip address. a hostname is required. PSCustomObject
$Results
collection here's the code ...
$4thOctetRange = 64..66
$IpBase = '192.168.1'
$ProcessList = @(
'AutoHotKey'
'BetterNotBeThere'
'DisplayFusion'
'Foobar2000'
)
$NoResponse = '__n/a__'
$Results = foreach ($4OR_Item in $4thOctetRange)
{
$Ip = '{0}.{1}' -f $IpBase, $4OR_Item
$Online = Test-Connection -ComputerName $Ip -Count 1 -Quiet
if ($Online)
{
# getting the hostname is REQUIRED by my version of Get-Process
# it will not accept an IP address
# version info = win7, ps5.1
# this may need adjusting for your returned hostname
# mine shows Hostname.attlocal.net
# that is not valid with any query i make, so i removed all after the 1st dot
$HostName = ([System.Net.Dns]::GetHostByAddress($Ip)).HostName.Split('.')[0]
}
else
{
$HostName = $NoResponse
}
$TempProps = [ordered]@{}
$TempProps.Add('IpAddress', $Ip)
$TempProps.Add('Online', $Online)
$TempProps.Add('HostName', $HostName)
foreach ($PL_Item in $ProcessList)
{
if ($TempProps['Online'])
{
# if the process aint found, the "SilentlyContinue" forces a $Null
# the "[bool]" then coerces that to a "False"
$TempProps.Add($PL_Item, [bool](Get-Process -ComputerName $HostName -Name $PL_Item -ErrorAction SilentlyContinue))
}
else
{
$TempProps.Add($PL_Item, $NoResponse)
}
}
# send the object out to the $Results collection
[PSCustomObject]$TempProps
}
# send to screen
$Results
# send to CSV file
$Results |
Export-Csv -LiteralPath "$env:TEMP\Senator14_RemoteProcessFinder.csv" -NoTypeInformation
truncated screen output ...
IpAddress : 192.168.1.65
Online : True
HostName : ZK_01
AutoHotKey : True
BetterNotBeThere : False
DisplayFusion : True
Foobar2000 : True
IpAddress : 192.168.1.66
Online : False
HostName : __n/a__
AutoHotKey : __n/a__
BetterNotBeThere : __n/a__
DisplayFusion : __n/a__
Foobar2000 : __n/a__
csv file content ...
"IpAddress","Online","HostName","AutoHotKey","BetterNotBeThere","DisplayFusion","Foobar2000"
"192.168.1.64","False","__n/a__","__n/a__","__n/a__","__n/a__","__n/a__"
"192.168.1.65","True","ZK_01","True","False","True","True"
"192.168.1.66","False","__n/a__","__n/a__","__n/a__","__n/a__","__n/a__"
Upvotes: 2