以下是我正在使用的代码:
$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
。
如果我逐个执行这些操作,则每个不同的流程都会返回runn1ng
,只是将所有流程组合在一起,然后返回fai1ed
。
附注(如果有人想知道):
runn1ng
和fai1ed
是'代码字'使用JavaScript替换为图像。我正在制作一个监控我的Windows服务器工作的HTML仪表板,所以请考虑绿色复选标记和红色x标记以及不是。spotify
被列为一个进程,因为我知道它是一个合法的进程,但未安装在我们的服务器上。当我编写脚本时,我最初在自己的个人计算机上进行了测试,并使用spotify
作为测试runn1ng
的方法,如果我打开它,或fai1ed
如果我关闭它。如果我的所有流程均为runn1ng
且spotify为fai1ed
,那么表明PS代码正在运行。似乎发生在PowerShell版本2中。
任何想法是什么导致它以及我如何重写它?
答案 0 :(得分:5)
if (($FoundProcesses | Select-Object -ExpandProperty Name) -contains $Item) {
PowerShell 3添加了一个名为member enumeration的东西。如果在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
}
}
答案 1 :(得分:2)
Patrick Meinecke's answer有效且有帮助,但让我尝试更详细的解释和更有效的解决方案:
首先要做的事情:你的代码在PSv3 + 中运行得很好,这应该提供激励我们将PSv2抛在后面。
PSv3引入了unified handling of scalars and collections through member enumeration ,它弥合了困扰PSv2的巨大标量/数组鸿沟。 -
具体来说,在PSv3中,您不必担心Get-Process -Name $ProcessesToCheckFor
是否碰巧返回单个或多个项:在任何一种情况下您都可以调用输出上的.Count
来计算返回的项目数,您可以在结果上调用成员(属性),在数组结果的情况下(多个项目)意味着在每个元素(例如,.Name
),结果可以根据需要再次用作标量或数组。
在 PSv2 - 中,您需要了解cmdlet(在情境上)是否恰好返回单个项目或多个,这意味着:
使用array-subexpression运算符@(...)
来确保即使附带的命令恰好返回单个项(标量),结果也是数组< / EM>
要收集新数组或标量中给定数组或标量元素的属性值,请再次使用... | Select-Object -ExpandProperty
,应用@(...)
以确保结果为数组。
请注意,PSv2- 部分统一标量/数组处理,但仅 管道处理:发送一个标量(单项)到管道,您可以按原样使用它,而无需将其包裹在@(...)
中:
'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
}
}