如何以特定方式格式化Powershell输出?
我需要扫描我的网络以查找服务器上的特定进程。我已经完成了以下脚本:如何以特定方式格式化Powershell输出?,powershell,Powershell,我需要扫描我的网络以查找服务器上的特定进程。我已经完成了以下脚本: 28..31 | ForEach-Object { Get-Process -ComputerName "192.168.0.$_" -Name svc* } 现在,我如何格式化输出,使其显示在哪个IP地址找到的过程中显示?多谢各位 这里有一种方法可以完成这项工作。[咧嘴笑]它的作用 构建ip最终八位字节范围 设置IPv4基本八位字节 生成要搜索的进程列表 设置“无响应”文本 在第四个八位组范围内迭代 生成IPv4地址 检查
28..31 | ForEach-Object { Get-Process -ComputerName "192.168.0.$_" -Name svc* }
现在,我如何格式化输出,使其显示在哪个IP地址找到的过程中显示?多谢各位 这里有一种方法可以完成这项工作。[咧嘴笑]它的作用
- 构建ip最终八位字节范围
- 设置IPv4基本八位字节
- 生成要搜索的进程列表
- 设置“无响应”文本
- 在第四个八位组范围内迭代
- 生成IPv4地址
- 检查它是否在线/正在响应
- 如果是,则获取主机名
对于我的PoSh[win7,ps5.1]版本,
cmdlet将不接受ip地址。需要主机名李>Get-Process
- 更正使用ATT进行inet服务时返回的损坏主机名
- 创建用于构建属性列表的有序哈希表
- 根据需要构建各种道具
- 将哈希表转换为
PSCustomObject
- 将其发送到
集合$Results
- 在屏幕上显示它
- 将其发送到CSV文件
$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
截短的屏幕输出
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文件内容
"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__"
这里有一种方法可以完成这项工作。[咧嘴笑]它的作用
- 构建ip最终八位字节范围
- 设置IPv4基本八位字节
- 生成要搜索的进程列表
- 设置“无响应”文本
- 在第四个八位组范围内迭代
- 生成IPv4地址
- 检查它是否在线/正在响应
- 如果是,则获取主机名
对于我的PoSh[win7,ps5.1]版本,
cmdlet将不接受ip地址。需要主机名李>Get-Process
- 更正使用ATT进行inet服务时返回的损坏主机名
- 创建用于构建属性列表的有序哈希表
- 根据需要构建各种道具
- 将哈希表转换为
PSCustomObject
- 将其发送到
集合$Results
- 在屏幕上显示它
- 将其发送到CSV文件
$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
截短的屏幕输出
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文件内容
"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__"
我建议切换到,因为:
- 它提供了一个远程执行任何命令的框架,而不是依赖单个cmdlet来支持
参数,并使用防火墙友好的传输-ComputerName
- PowerShell[Core]v6+将继续支持它,不再支持cmdlet单个参数
参数;此过时的远程处理方法使用的是一种较旧的、不太适合防火墙的远程处理形式,而-Observed-since v3-WMI cmdlet也使用这种形式(后者被CIM cmdlet取代)-ComputerName
Invoke Command
,Enter-PSSession
,…)一致使用
如果使用调用命令
以目标(多台)远程计算机为目标,则返回的对象将通过自动添加的.PSComputerName
属性自动包含并显示原始计算机的名称:
# 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* }
您将看到如下输出-注意PSComputerName
列:
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
...
请注意,您可以使用调用命令-HideComputerName
参数来禁止自动显示.PSComputerName
属性。
但是,该属性仍然以编程方式可用,这允许您执行以下操作:
Invoke-Command -ComputerName $ips { Get-Process -Name svc* } -HideComputerName |
Format-Table -GroupBy PSComputerName
这将产生按计算机名/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
...
如果要在分组之前按IP地址进行排序,可以在调用格式表之前插入
|sort Object{[version]$.PSComputerName}
[1]
对于按计算机名排序的,只需
|排序对象PSComputerName
就可以了
[1] 转换到[version]
是确保IP地址正确排序的技巧;IP地址字符串可以解释为[version]
(System.version
)实例,这些实例可以直接比较,使用版本组件的数值(首先是.MajorVersion
,然后是.MinorVersion
,…)我建议切换到,因为:
- 它提供了一个远程执行任何命令的框架,而不是依赖单个cmdlet来支持
-ComputerName
参数,并使用防火墙友好的传输
- PowerShell[Core]v6+将继续支持它,不再支持cmdlet单个参数
-ComputerName
参数;此过时的远程处理方法使用的是一种较旧的、不太适合防火墙的远程处理形式,而-Observed-since v3-WMI cmdlet也使用这种形式(后者被CIM cmdlet取代)
因此,最好将防火墙友好型PowerShell远程处理与其通用远程处理命令(Invoke Command
,Enter-PSSession
,…)一致使用
如果使用调用命令
以目标(多台)远程计算机为目标,则返回的对象将通过自动添加的.PSComputerName
属性自动包含并显示原始计算机的名称:
# 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* }
您将看到如下输出-注意PSComputerName
列:
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
...
请注意,您可以使用Invoke命令的-HideCo来抑制.PSComputerName
属性的自动显示