Powershell脚本输出已安装的程序

时间:2010-05-18 06:26:42

标签: powershell wmi ps1

我想使用win32_product wmi类来做到这一点。

我需要脚本来简单地计算安装的产品数量,并输出执行脚本所需的时间。

我的atm似乎无法正常工作:

    $count = 0
    $products = get-wmiobject -class "Win32_Product"
    foreach ($product in $products) {
          if ($product.InstallState -eq 5) {
                count++
          }
    }
    write-host count

3 个答案:

答案 0 :(得分:3)

小心!使用WMI的Win32_Product课程,问题与之前的2个答案有关,不建议用于此目的。

简而言之:使用Win32_Product 是一个无害的查询,因为它有副作用。引用微软,“[它] ...启动对已安装软件包的一致性检查,验证并修复安装。” (强调我的)

参考文献:


那么什么是更好(更安全)的解决方案?

Marc Carter,在上面的 Hey,Scripting Guy!博客中编写了客座专栏,第一次抽射,提供自定义PowerShell功能,在我的系统上它只返回了一半的条目Win32_Product调用。此外,它是很多代码(3打左右)。然而,在他的帖子的评论中,knutkj提供了这个更短的版本,可以做同样的事情:

Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |
   Get-ItemProperty |
   Sort-Object -Property DisplayName |
   Select-Object -Property DisplayName, DisplayVersion, InstallLocation

但正如我所说,它确实如此:不提供完整的清单。但这是一个开始。

后来在评论中,Nick W报告说实际上有3个感兴趣的注册表路径,但并非所有系统都存在。此外,在查看这3条路径时,必须进行一些额外的过滤。

结合这两者,添加一些输出字段,并使代码在严格模式下运行安全,我得出了这个简单的解决方案:

function Get-InstalledPrograms()
{
    $regLocations = (
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\", 
        "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\",
        "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
        )

    Get-ChildItem ($regLocations | Where { Test-Path $_ } ) |
        Get-ItemProperty |
        Where {
            ( (Get-Member -InputObject $_ -Name DisplayName) -and $_.DisplayName -ne $Null) -and
            (!(Get-Member -InputObject $_ -Name SystemComponent) -or $_.SystemComponent -ne "1") -and 
            (!(Get-Member -InputObject $_ -Name ParentKeyName) -or $_.ParentKeyName -eq $Null)
            } |
        Sort DisplayName |
        Select DisplayName, DisplayVersion, Publisher, InstallLocation, InstallDate,  URLInfoAbout
}

答案 1 :(得分:2)

Roman Kuzmin对这个错字很正确。纠正几乎可以解决所有问题。

为了使它变得更加强大,我会使用

get-wmiobject -class "Win32_Product" | 
    ? { $_.InstallState -eq 5 } |
    measure-object  | 
    select -exp Count

考虑到时间,你可以把它包装成measure-command

measure-command { 
  $count = get-wmiobject -class "Win32_Product" | 
              ? { $_.InstallState -eq 5 } | 
              measure-object  |
              select -exp Count
  write-host Count: $count
}

答案 2 :(得分:2)

这有点晚了,但是“更有权力的方式”:

$(Get-WmiObject -Class "Win32_Product" -Filter "InstallState=5").Count