【问题标题】:How to Return a Pretty Zero Value with the Count Property from Get-Process?如何使用 Get-Process 中的 Count 属性返回一个相当零的值?
【发布时间】:2011-11-29 13:19:12
【问题描述】:

比较以下三个脚本:

示例 1

$a = GPS | Where {$_.ProcessName -Match 'AcroRd32'}
$a
$a.Count

If ($a.Count -Eq 0)
{
    Echo "Adobe Reader is Off"
}
Else
{
    Echo "Adobe Reader is On"
}

# If Adobe Reader is not running, how come 0 (zero) is not returned?
# This is prettier, should I use it?  Or does it slow down performance?



示例 2

$a = GPS AcroRd32
$a
$a.Count

If ($a.Count -Eq 0)
{
    Echo "Adobe Reader is Off"
}
Else
{
    Echo "Adobe Reader is On"
}

# If Adobe Reader is not running, how come 0 (zero) is not returned?
# This is uglier, but it doesn't have to pipe any output, so does it have any performance gains?



示例 3

GPS AcroRd32 | Measure | Select -Expand Count

# 0 (zero) is returned, but with an ugly Error



我想我的部分问题是我将 PowerShell 视为 VBS;以这种方式/风格编写代码通常会给我一个整数值零并且不会引发任何错误(当然,如果 Adob​​e Reader 已关闭)。检查程序实例未运行的正确 PowerShell 方法是什么? cmets 中的性能问题次于“PowerShell Way”问题。

附:老实说,第三个样本返回的错误信息不会破坏任何东西,它只是丑陋,所以它并没有超出实际用途,所以我想真正的问题是我只是一个美学的傻瓜=^D

【问题讨论】:

    标签: powershell powershell-2.0 stderr


    【解决方案1】:

    这是一个常见的 PowerShell 问题。命令可以返回:

    • Nothing ~ null(没有属性Count,获取它要么为空,要么失败)
    • 单个对象(它可能有自己的属性Count 属性,最令人困惑的情况——可以返回任何东西;或者可能没有它,然后获取Count 为空或失败)
    • 2+ 对象数组,其属性为Count

    解决方案很简单。当您确实需要返回对象的计数时,请使用 @() 运算符。结果始终是具有属性Count 的数组。

    # this is always an array
    $result = @(<command returning something or nothing>)
    
    # this is always a number:
    $result.Count
    

    【讨论】:

    • @() 运算符与第一个示例的初始变量赋值相结合,使其美观且实用 - $a = @(GPS | Where {$_.ProcessName -Match 'AcroRd32'})。为了满足学究的冲动,我必须问,与仅仅做$a = @(GPS AcroRd32)相比,美学的努力(从GPSWhere的管道)会导致性能下降吗?如果是这样,我意识到这将是微不足道的,不会被我们注意到,但我仍然想知道,这样我就可以让自己不那么无知了 XD
    • 我测量了一个“远”进程:@(Get-Process far) ~ 1.6 毫秒。 @(Get-Process | where { $_.ProcessName -eq 'far' }) ~ 6.8 毫秒。根据我的经验,Where-ObjectForEach-Object 基本上非常慢,我在脚本中避免使用它们(在 V2.0 中这总是可能的)。但它们在命令行输入时仍然很方便。
    • 顺便说一句,如果您使用@(GPS AcroRd32),那么当进程不存在时,请准备好出错。如果错误首选项是Stop,它会很慢或者可能会失败。为避免错误,您可以使用此技巧:stackoverflow.com/questions/4362275/…。那么@(GPS [A]croRd32) 应该是性能最好的。
    • 迷人的通配符解决方法!我应该查看哪些资源以熟悉所有这些 PowerShell 特性?
    • 这个网站绝对是最好的搜索资源之一:例如。输入[powershell],搜索,按投票排序,享受:stackoverflow.com/questions/tagged/…
    【解决方案2】:

    我建议你这样做:

    $count = @(get-process | ?{$_.ProcessName -eq "AcroRd32"}).count
    
    if($count -eq 0){
    
    write-host "Adobe Reader is Off"
    
    } else{
    
    write-host "Adobe Reader is On"
    
    }
    

    上面所做的是将返回的对象强制放入一个数组中,因此如果没有运行读取器进程,您将获得一个空数组,因此其计数为零。当你确实有进程时,你将它们放在数组中,并且你得到非零计数,上面的代码将按预期工作。

    基于 Sample2 / Sample3 的替代方案:

    $acrobat = gps AcroRd32 -ErrorAction SilentlyContinue
    if($acrobat){
    
        write-host "Adobe Reader is On"
    
    } else{
    
        write-host "Adobe Reader is Off"
    
    }
    

    在上面,如果阅读器没有运行,我们会抑制错误。然后,如果设置了 $acrobat,就知道阅读器正在运行。

    对您的代码的观察:

    当阅读器未运行时,$a 不会被分配任何内容,因此 $a.Count -eq 0 将为 false。当 reader 运行时,$a 被分配了那些进程对象,你得到 $a.Count 为 1 或更多,因此再次为 false。因此,您将始终知道阅读器处于开启状态。

    【讨论】:

      【解决方案3】:

      您在第三个示例中提到了错误 - 您可以使用 SilentlyContinue ErrorAction 隐藏消息:

      GPS -ea silentlycontinue AcroRd32 | Measure | Select -Expand Count
      

      【讨论】:

        猜你喜欢
        • 2010-12-08
        • 2014-07-31
        • 2018-09-07
        • 1970-01-01
        • 2013-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多