Скрипт Powershell для вывода установленных программ - PullRequest
1 голос
/ 18 мая 2010

Я хотел бы сделать это с помощью класса wmi win32_product.

Мне нужен скрипт, чтобы просто посчитать количество установленных продуктов и вывести время, затраченное на его выполнение.* То, что у меня есть, кажется, не работает правильно:

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

Ответы [ 3 ]

3 голосов
/ 04 августа 2014

Осторожно! При использовании класса WMI Win32_Product, который делают вопрос и предыдущие 2 ответа, для этой цели не рекомендуется.

В двух словах: использование Win32_Product равно , а не безвредному запросу, поскольку он имеет побочные эффекты. Цитируя Microsoft, «[Это] ... инициирует проверку согласованности установленных пакетов, проверяя и восстанавливая установки». (выделение мое)

Ссылки:


Так что же является лучшим (более безопасным) решением?

Марк Картер, пишущий гостевую колонку в блоге Hey, Scripting Guy! , занимает первый залп, предоставляя пользовательскую функцию PowerShell, и в моей системе он возвратил только вдвое меньше записей, чем Win32_Product призывание. Также много кода (около трех десятков строк). Однако в комментариях к своему посту knutkj предлагает гораздо более короткую версию, которая делает то же самое:

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

Но, как я уже сказал, он делает то же самое: не предоставляет полный список. Но это только начало.

Позже в комментариях Ник У сообщил, что на самом деле существует 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
}
2 голосов
/ 16 февраля 2011

Немного опоздал, но "более мощный способ":

$(Get-WmiObject -Class "Win32_Product" -Filter "InstallState=5").Count
2 голосов
/ 18 мая 2010

Роман Кузьмин прав насчет опечатки. Исправление решит практически все.

Чтобы сделать его более мощным, я бы использовал

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
}
...