Senator14
Senator14

Reputation: 159

how to format Powershell output in specific way?

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

Answers (2)

mklement0
mklement0

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

Lee_Dailey
Lee_Dailey

Reputation: 7479

here's one way to do the job. [grin] what it does ...

  • builds the ip final octet range
  • sets the IPv4 base octets
  • builds the list of processes to search for
  • sets the "no response" text
  • iterates thru the 4th octet range
  • builds the IPv4 address
  • checks to see if it is online/responding
  • if so, gets the hostname
    for my version of PoSh [win7, ps5.1] the Get-Process cmdlet will NOT accept an ip address. a hostname is required.
  • corrects for the damaged hostname returned when one uses ATT for inet service
  • creates an ordered hashtable to use for building the property list
  • builds the various props as needed
  • converts the hashtable to a PSCustomObject
  • sends that to the $Results collection
  • shows it on screen
  • sends it to a CSV file

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

Related Questions