none
Скрипт для сбора информации об установленных обновлениях на серверах RRS feed

  • Вопрос

  • Пробовал скрипт из этой темы

    https://social.technet.microsoft.com/Forums/ru-RU/3d792941-2969-489a-93c5-5065450206c7/1040-108210721082-1074-powershell-108010791103109710851086?forum=scrlangru

    Но отдает не актуальное количество обновлений на сервере (сравниваю с Панель управления - Установленные обновления)

    Среда смешанная 2k8,2k12r2,2k16, где то отдает нужное количество по сравнению с тем, что в Панели управления, а где-то меньше. Скорее всего не учитывает обновления, которые были установлены при подготовке установочного образа.

    12 августа 2018 г. 21:54

Ответы

  • На сколько скильно различаются результаты?

    $sum = 0
    
    # Products
    $pr = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\"
    $u1 = Get-ChildItem -Path $pr | ForEach-Object {
        Get-ChildItem -Path "$($_.PSPath)\Products" | ForEach-Object {
            $ppatch = "$($_.PSPath)\Patches"
            $haspatch = Get-ItemProperty -Path $ppatch -Name AllPatches -ErrorAction SilentlyContinue
    
            if($haspatch.AllPatches) {
                $iprop =  Get-ItemProperty -Path "$($_.PSPath)\InstallProperties" -Name DisplayName,SystemComponent -ErrorAction SilentlyContinue
                if($iprop.SystemComponent -ne 1) {
                    $haspatch.AllPatches | Foreach-Object {"$ppatch\$_"} | Get-ItemProperty -Name DisplayName | ForEach-Object {
                        [PSCustomObject]@{
                            DisplayName = $iprop.DisplayName
                            KB = $_.DisplayName
                        }
                    }
                }
            }
        }
    } 
    $u1 | Format-Table -GroupBy DisplayName
    
    # Packages
    $installed = 0x70
    $rcbs = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\"
    $lcsb = "C:\Windows\servicing\Packages"
    $u2 = Get-ChildItem $rcbs| Get-ItemProperty  | Where-Object {"UpdateAgentLCU","WindowsUpdateAgent","DISM Package Manager Provider" -contains $_.InstallClient -and $_.CurrentState -eq $installed} | ForEach-Object {
        $in = $_.InstallName
        
        if($in -eq "update.mum") {
            $in = $_.PsChildName + ".mum"
        }
    
        $nlcsb = Join-Path $lcsb $in
        $xml = [xml](Get-Content $nlcsb)
        $kb = $xml.assembly.package.identifier
        $type = $xml.assembly.package.releaseType
    
        if($kb -match "KB\d+" -and $type -match "(Update|Hotfix)") {
            $name = $xml.assembly.DisplayName
    
            if($name -notmatch "Security") {
                if($type -eq "Update") {
                    $name = "Update for Microsoft Windows ($kb)"
                } else {
                    $name = "Security Update for Microsoft Windows ($kb)"
                }
            }
    
            [PSCustomObject]@{
                DisplayName = $name
                KB = $kb
            }
        }
    } | Sort KB -Unique
    
    $u2
    
    # Uninstall
    $rk = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\","HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
    
    $u3 = Get-ChildItem $rk -Recurse -ErrorAction 0 | Get-ItemProperty -Name "DisplayName",ParentDisplayName -ErrorAction 0 | ? {$_.DisplayName -match "KB\d+"} | % {
    	$n = $_.DisplayName
        $p = $_.ParentDisplayName
    
        if(!$p) {
            $p = "Unspecified"
        }
        [PSCustomObject]@{
                DisplayName = $n 
                KB = ($n -split "[()]" -match "KB")[0]
                ParentDisplayName = $p
            }
    } | Sort-Object ParentDisplayName,DisplayName
    
    $u3 | Format-Table -GroupBy ParentDisplayName
    
    "`n`nTotal updates: {0}" -f (@($u1).count + @($u2).count+@($u3).count)
    


    • Изменено KazunEditor 13 августа 2018 г. 22:16
    • Помечено в качестве ответа PavlovP 16 августа 2018 г. 11:50
    13 августа 2018 г. 21:46
    Отвечающий

Все ответы

  • так а wsus у вас нет часом?

    в упомянутой вами теме был линк на другую подобную тему, вы пробовали ее смотреть?


    The opinion expressed by me is not an official position of Microsoft

    12 августа 2018 г. 22:01
    Модератор
  • Попробовать поставить модуль PSWindowsUpdate и посмотреть вывод командлетов:

    Install-Module PSWindowsUpdate -Force
    Get-WuHistory
    Get-WUList -IsInstalled
    

    13 августа 2018 г. 6:26
    Отвечающий
  • так а wsus у вас нет часом?

    в упомянутой вами теме был линк на другую подобную тему, вы пробовали ее смотреть?


    The opinion expressed by me is not an official position of Microsoft

    WSUS развернут недавно, до этого обновления ставились без него. Не совсем представляю, как с помощью него получить информацию.
    13 августа 2018 г. 8:53
  • Попробовать поставить модуль PSWindowsUpdate и посмотреть вывод командлетов:

    Install-Module PSWindowsUpdate -Force
    Get-WuHistory
    Get-WUList -IsInstalled

    Первая команда отдает 49 обновлений.

    Вторая 75. 

    В панели управления вижу 126 обновлений.

    13 августа 2018 г. 9:25
  • Покажите скрин из панели управления и реестра, в которой выдается меньше обновлений и какой путь в реестре используется для данного KBxxxxx.

    $rk = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Updates\",
    	"HKLM:\SOFTWARE\Microsoft\Updates\",
    	"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\",
    	"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
    
    $updates = @{}
    
    Get-ChildItem $rk -Recurse -ErrorAction 0 | Get-ItemProperty -Name "(Default)","DisplayName" -ErrorAction 0 | ? {$_.DisplayName -match "KB\d+" -or $_."(Default)" -match "KB\d+"} | % {
    	if($_.DisplayName) 
    	{
    		$_.DisplayName
    	}
    	else
    	{
    		$_."(default)"
    	}
    } | Foreach {$updates[$_] += 1}
    
    $p = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\"
    Get-ChildItem $p | Get-ItemProperty | Where InstallLocation -match "KB\d+" | Sort InstallLocation -Uniq | Foreach {$_.InstallLocation.split("-") -match "KB"} | Foreach {
    	if(!$updates.ContainsKey($_)) { $updates[$_] += 1}
    }
    
    $p = "HKLM:\SOFTWARE\Classes\Installer\Patches"
    Get-ChildItem $p -Recurse | Get-ItemProperty | Where PackageName -match "KB\d+" | Foreach {($_.PackageName -split "[-_.]" -match "KB\d+").ToUpper()} | Foreach {
    	if(!$updates.ContainsKey($_)) { $updates[$_] += 1}
    }
    
    $updates.GetEnumerator() | Sort Name
    
    "`n`nTotal Updates: {0}" -f ($updates.GetEnumerator() |  Measure Value -Sum).Sum 

    13 августа 2018 г. 11:11
    Отвечающий
  • Покажите скрин из панели управления и реестра, в которой выдается меньше обновлений и какой путь в реестре используется для данного KBxxxxx.

    $rk = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Updates\",
    	"HKLM:\SOFTWARE\Microsoft\Updates\",
    	"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\",
    	"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
    
    $updates = @{}
    
    Get-ChildItem $rk -Recurse -ErrorAction 0 | Get-ItemProperty -Name "(Default)","DisplayName" -ErrorAction 0 | ? {$_.DisplayName -match "KB\d+" -or $_."(Default)" -match "KB\d+"} | % {
    	if($_.DisplayName) 
    	{
    		$_.DisplayName
    	}
    	else
    	{
    		$_."(default)"
    	}
    } | Foreach {$updates[$_] += 1}
    
    $p = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\"
    Get-ChildItem $p | Get-ItemProperty | Where InstallLocation -match "KB\d+" | Sort InstallLocation -Uniq | Foreach {$_.InstallLocation.split("-") -match "KB"} | Foreach {
    	if(!$updates.ContainsKey($_)) { $updates[$_] += 1}
    }
    
    $p = "HKLM:\SOFTWARE\Classes\Installer\Patches"
    Get-ChildItem $p -Recurse | Get-ItemProperty | Where PackageName -match "KB\d+" | Foreach {($_.PackageName -split "[-_.]" -match "KB\d+").ToUpper()} | Foreach {
    	if(!$updates.ContainsKey($_)) { $updates[$_] += 1}
    }
    
    $updates.GetEnumerator() | Sort Name
    
    "`n`nTotal Updates: {0}" -f ($updates.GetEnumerator() |  Measure Value -Sum).Sum 

    Результат выполнения скрипта:

    Панель управления

    Скрипт отдал больше обновлений, чем показывает в Панели управления.
    • Изменено PavlovP 13 августа 2018 г. 11:25
    13 августа 2018 г. 11:24
  • На сколько скильно различаются результаты?

    $sum = 0
    
    # Products
    $pr = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\"
    $u1 = Get-ChildItem -Path $pr | ForEach-Object {
        Get-ChildItem -Path "$($_.PSPath)\Products" | ForEach-Object {
            $ppatch = "$($_.PSPath)\Patches"
            $haspatch = Get-ItemProperty -Path $ppatch -Name AllPatches -ErrorAction SilentlyContinue
    
            if($haspatch.AllPatches) {
                $iprop =  Get-ItemProperty -Path "$($_.PSPath)\InstallProperties" -Name DisplayName,SystemComponent -ErrorAction SilentlyContinue
                if($iprop.SystemComponent -ne 1) {
                    $haspatch.AllPatches | Foreach-Object {"$ppatch\$_"} | Get-ItemProperty -Name DisplayName | ForEach-Object {
                        [PSCustomObject]@{
                            DisplayName = $iprop.DisplayName
                            KB = $_.DisplayName
                        }
                    }
                }
            }
        }
    } 
    $u1 | Format-Table -GroupBy DisplayName
    
    # Packages
    $installed = 0x70
    $rcbs = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\"
    $lcsb = "C:\Windows\servicing\Packages"
    $u2 = Get-ChildItem $rcbs| Get-ItemProperty  | Where-Object {"UpdateAgentLCU","WindowsUpdateAgent","DISM Package Manager Provider" -contains $_.InstallClient -and $_.CurrentState -eq $installed} | ForEach-Object {
        $in = $_.InstallName
        
        if($in -eq "update.mum") {
            $in = $_.PsChildName + ".mum"
        }
    
        $nlcsb = Join-Path $lcsb $in
        $xml = [xml](Get-Content $nlcsb)
        $kb = $xml.assembly.package.identifier
        $type = $xml.assembly.package.releaseType
    
        if($kb -match "KB\d+" -and $type -match "(Update|Hotfix)") {
            $name = $xml.assembly.DisplayName
    
            if($name -notmatch "Security") {
                if($type -eq "Update") {
                    $name = "Update for Microsoft Windows ($kb)"
                } else {
                    $name = "Security Update for Microsoft Windows ($kb)"
                }
            }
    
            [PSCustomObject]@{
                DisplayName = $name
                KB = $kb
            }
        }
    } | Sort KB -Unique
    
    $u2
    
    # Uninstall
    $rk = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\","HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
    
    $u3 = Get-ChildItem $rk -Recurse -ErrorAction 0 | Get-ItemProperty -Name "DisplayName",ParentDisplayName -ErrorAction 0 | ? {$_.DisplayName -match "KB\d+"} | % {
    	$n = $_.DisplayName
        $p = $_.ParentDisplayName
    
        if(!$p) {
            $p = "Unspecified"
        }
        [PSCustomObject]@{
                DisplayName = $n 
                KB = ($n -split "[()]" -match "KB")[0]
                ParentDisplayName = $p
            }
    } | Sort-Object ParentDisplayName,DisplayName
    
    $u3 | Format-Table -GroupBy ParentDisplayName
    
    "`n`nTotal updates: {0}" -f (@($u1).count + @($u2).count+@($u3).count)
    


    • Изменено KazunEditor 13 августа 2018 г. 22:16
    • Помечено в качестве ответа PavlovP 16 августа 2018 г. 11:50
    13 августа 2018 г. 21:46
    Отвечающий
  • Да, вот этот скрипт подошел. Есть пара нюансов правда, на одном из серверов он посчитал лишнее обновление для SilverLight

    И на Windows 7 он не считает все обновления. Но для 2012r2 и 2016 вполне подходит и позволил мне выполнить задачу. Спасибо!

    16 августа 2018 г. 11:50