在 PowerShell 版本 2 中检查进程和进程状态并根据单个进程或多个进程获得两个不同的输出?
Checking for process and process status in PowerShell version 2 and getting two different outputs depending on single process or multiple processes?
下面是我正在使用的代码:
$ProcessesToCheckFor = (
'company_name_uat-Historian'
)
$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue
foreach ($Item in $ProcessesToCheckFor)
{
if ($FoundProcesses.Name -contains $Item)
{
'{0} runn1ng' -f $Item
}
else
{
'{0} fai1ed' -f $Item
}
}
代码检查服务器上的company_name_uat-Historian
进程是否为运行,如果是运行,则输出runn1ng
和fai1ed
如果没有。
问题是,就像上面的代码一样,它只检查一个进程时有效,但当您尝试检查进程列表时却无效。
我需要检查进程列表,所以当我按如下所示链接其余进程时:
$ProcessesToCheckFor = (
'company_name_uat-Historian',
'company_name_uat-KEReviewCollector',
'company_name_uat-lwm',
'company_name_uat-MQAck',
'company_name_uat-MQOutput',
'company_name_uat-SQAC',
'company_name_uat-Store',
'company_name_uat-Store_STS',
'company_name_uat-StoreLegacy',
'spotify'
)
$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue
foreach ($Item in $ProcessesToCheckFor)
{
if ($FoundProcesses.Name -contains $Item)
{
'{0} runn1ng' -f $Item
}
else
{
'{0} fai1ed' -f $Item
}
他们都输出fai1ed
.
如果我一个一个地做,每个不同的过程都会 return runn1ng
,只是全部聚集在一起 return fai1ed
.
旁注(如果有人想知道的话):
runn1ng
和 fai1ed
是 'code words',使用 JavaScript 替换为图像。我正在制作一个 HTML 仪表板来监控我的 Windows 服务器的工作,所以想想绿色复选标记和红色 x 标记等等。
- 使用PowerShell version 2根本不是我的选择,我负责监控的一些服务器是Windows 2008 R2。我相信它们会在今年某个时候更新,但项目可交付成果要求我立即制定监控解决方案。还有一些我喜欢为其编写 PowerShell 脚本的 2012 年服务器。
spotify
被列为一个进程,因为我知道它是一个合法的进程,但没有安装在我们的服务器上。当我编写脚本时,我最初在自己的个人计算机上进行测试,并使用 spotify
作为测试打开它时 runn1ng
或关闭它时 fai1ed
的手段。如果我的所有进程都是 runn1ng
而 spotify 是 fai1ed
,那么这表明 PS 代码正在运行。
它似乎发生在 PowerShell 版本 2 中。
知道是什么原因造成的吗?我该如何重写它?
答案
if (($FoundProcesses | Select-Object -ExpandProperty Name) -contains $Item) {
为什么
PowerShell 3 添加了一个叫做成员枚举的东西。如果在 2.0 中有对象数组,则不能直接调用数组的属性,因为它会在数组对象本身上查找那些属性。在 3.0+ 中,如果数组中不存在该成员,它也会检查该成员的项目。使用 Select-Object -ExpandProperty
是调用成员的更明确的方式。
您也可以将 Get-Process
调用移动到 foreach
循环中。
foreach ($Item in $ProcessesToCheckFor)
{
if (Get-Process -Name $Item -ErrorAction SilentlyContinue)
{
'{0} runn1ng' -f $Item
}
else
{
'{0} fai1ed' -f $Item
}
}
有效且有帮助,但让我尝试更详细的解释和更有效的解决方案:
首先要做的事情:您的代码在 PSv3+ 中工作得很好,这应该会激励人们放弃 PSv2。
PSv3 引入了 unified handling of scalars and collections through member(-access) enumeration,它弥合了困扰 PSv2-的巨大 scalar/array 鸿沟。
具体来说,在 PSv3 中,您不必担心 Get-Process -Name $ProcessesToCheckFor
是否发生在 return 一个 单个 或 多个 items:在任何一种情况下,您都可以在输出上调用 .Count
来计算 returned 的项目数,并且您可以在结果上调用成员 (属性),其中,数组结果(多项)的情况意味着在每个元素(例如,.Name
)上调用成员,并且结果可以再次用作标量或数组根据需要.
但是,在 PSv2- 中,您需要了解一个 cmdlet 在特定情况下是 return 一个项目还是多个项目ones,意思是:
使用数组子表达式运算符@(...)
确保即使封闭的命令恰好return一个单个项目(标量),结果是一个 array.
要收集给定数组或新数组或标量中标量的元素的 属性 值,请使用 ... | Select-Object -ExpandProperty
- 再次应用 @(...)
以确保结果是 array.
请注意,PSv2- 有 一些 统一的 scalar/array 处理,但 只有 关于 pipeline processing: 将一个标量(单项)发送到管道,你可以按原样使用它,而不需要将它包装在 @(...)
:
'foo' | ...
工作正常 - 不需要 @('foo') | ...
(即使它也有效)。
应用于您的代码我们得到:
$ProcessesToCheckFor = (
'company_name_uat-Historian',
'company_name_uat-KEReviewCollector',
'company_name_uat-lwm',
'company_name_uat-MQAck',
'company_name_uat-MQOutput',
'company_name_uat-SQAC',
'company_name_uat-Store',
'company_name_uat-Store_STS',
'company_name_uat-StoreLegacy',
'spotify'
)
# Collect the names of all running processes and
# make sure the result is an array (`@(...)`).
$FoundProcesses = @(Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty Name)
foreach ($Item in $ProcessesToCheckFor) {
if ($FoundProcesses -contains $Item) {
'{0} runn1ng' -f $Item
} else {
'{0} fai1ed' -f $Item
}
}
下面是我正在使用的代码:
$ProcessesToCheckFor = (
'company_name_uat-Historian'
)
$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue
foreach ($Item in $ProcessesToCheckFor)
{
if ($FoundProcesses.Name -contains $Item)
{
'{0} runn1ng' -f $Item
}
else
{
'{0} fai1ed' -f $Item
}
}
代码检查服务器上的company_name_uat-Historian
进程是否为运行,如果是运行,则输出runn1ng
和fai1ed
如果没有。
问题是,就像上面的代码一样,它只检查一个进程时有效,但当您尝试检查进程列表时却无效。
我需要检查进程列表,所以当我按如下所示链接其余进程时:
$ProcessesToCheckFor = (
'company_name_uat-Historian',
'company_name_uat-KEReviewCollector',
'company_name_uat-lwm',
'company_name_uat-MQAck',
'company_name_uat-MQOutput',
'company_name_uat-SQAC',
'company_name_uat-Store',
'company_name_uat-Store_STS',
'company_name_uat-StoreLegacy',
'spotify'
)
$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue
foreach ($Item in $ProcessesToCheckFor)
{
if ($FoundProcesses.Name -contains $Item)
{
'{0} runn1ng' -f $Item
}
else
{
'{0} fai1ed' -f $Item
}
他们都输出fai1ed
.
如果我一个一个地做,每个不同的过程都会 return runn1ng
,只是全部聚集在一起 return fai1ed
.
旁注(如果有人想知道的话):
runn1ng
和fai1ed
是 'code words',使用 JavaScript 替换为图像。我正在制作一个 HTML 仪表板来监控我的 Windows 服务器的工作,所以想想绿色复选标记和红色 x 标记等等。- 使用PowerShell version 2根本不是我的选择,我负责监控的一些服务器是Windows 2008 R2。我相信它们会在今年某个时候更新,但项目可交付成果要求我立即制定监控解决方案。还有一些我喜欢为其编写 PowerShell 脚本的 2012 年服务器。
spotify
被列为一个进程,因为我知道它是一个合法的进程,但没有安装在我们的服务器上。当我编写脚本时,我最初在自己的个人计算机上进行测试,并使用spotify
作为测试打开它时runn1ng
或关闭它时fai1ed
的手段。如果我的所有进程都是runn1ng
而 spotify 是fai1ed
,那么这表明 PS 代码正在运行。
它似乎发生在 PowerShell 版本 2 中。
知道是什么原因造成的吗?我该如何重写它?
答案
if (($FoundProcesses | Select-Object -ExpandProperty Name) -contains $Item) {
为什么
PowerShell 3 添加了一个叫做成员枚举的东西。如果在 2.0 中有对象数组,则不能直接调用数组的属性,因为它会在数组对象本身上查找那些属性。在 3.0+ 中,如果数组中不存在该成员,它也会检查该成员的项目。使用 Select-Object -ExpandProperty
是调用成员的更明确的方式。
您也可以将 Get-Process
调用移动到 foreach
循环中。
foreach ($Item in $ProcessesToCheckFor)
{
if (Get-Process -Name $Item -ErrorAction SilentlyContinue)
{
'{0} runn1ng' -f $Item
}
else
{
'{0} fai1ed' -f $Item
}
}
首先要做的事情:您的代码在 PSv3+ 中工作得很好,这应该会激励人们放弃 PSv2。
PSv3 引入了 unified handling of scalars and collections through member(-access) enumeration,它弥合了困扰 PSv2-的巨大 scalar/array 鸿沟。
具体来说,在 PSv3 中,您不必担心 Get-Process -Name $ProcessesToCheckFor
是否发生在 return 一个 单个 或 多个 items:在任何一种情况下,您都可以在输出上调用 .Count
来计算 returned 的项目数,并且您可以在结果上调用成员 (属性),其中,数组结果(多项)的情况意味着在每个元素(例如,.Name
)上调用成员,并且结果可以再次用作标量或数组根据需要.
但是,在 PSv2- 中,您需要了解一个 cmdlet 在特定情况下是 return 一个项目还是多个项目ones,意思是:
使用数组子表达式运算符
@(...)
确保即使封闭的命令恰好return一个单个项目(标量),结果是一个 array.要收集给定数组或新数组或标量中标量的元素的 属性 值,请使用
... | Select-Object -ExpandProperty
- 再次应用@(...)
以确保结果是 array.请注意,PSv2- 有 一些 统一的 scalar/array 处理,但 只有 关于 pipeline processing: 将一个标量(单项)发送到管道,你可以按原样使用它,而不需要将它包装在
@(...)
:
'foo' | ...
工作正常 - 不需要@('foo') | ...
(即使它也有效)。
应用于您的代码我们得到:
$ProcessesToCheckFor = (
'company_name_uat-Historian',
'company_name_uat-KEReviewCollector',
'company_name_uat-lwm',
'company_name_uat-MQAck',
'company_name_uat-MQOutput',
'company_name_uat-SQAC',
'company_name_uat-Store',
'company_name_uat-Store_STS',
'company_name_uat-StoreLegacy',
'spotify'
)
# Collect the names of all running processes and
# make sure the result is an array (`@(...)`).
$FoundProcesses = @(Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty Name)
foreach ($Item in $ProcessesToCheckFor) {
if ($FoundProcesses -contains $Item) {
'{0} runn1ng' -f $Item
} else {
'{0} fai1ed' -f $Item
}
}