На сайте клиента мы используем службы Windows Server Update Services (WSUS) для развертывания обновлений продуктов на компьютерах в сети. Прежде чем служба WSUS установит обновления продуктов, необходимо вручную утвердить их для установки или включить режим автоматического утверждения, в котором нельзя выбирать устанавливаемые обновления (устанавливаются все). .
Работа ApproveUpdates.ps1 начинается с загрузки файла RequiredUpdates.txt, содержащего заголовок каждого обновления, как показано на экране. После проверки содержимого текстового файла выполняется инициализация счетчиков и файлов журналов. Сценарий записывает данные в пять журналов: found.log, expired.log, approved.log, failed.log и missing.log.
![]() |
| Экран. Тестовый файл RequiredUpdates.txt |
Затем сценарий ApproveUpdates.ps1 загружает сборку Microsoft.UpdateServices.Administration, которая обеспечивает использование API-интерфейса Windows.NET Framework для подключения к серверу WSUS. В частности, метод Get UpdateServer класса AdminProxy передает интерфейс (с типом данных IUpdate Server) в сервер WSUS и вносит этот интерфейс в переменную $UpdateServer.
Интерфейс IUpdateServer используется для выполнения двух важных задач, как показано в листинге. Сначала сценарий задействует метод GetComputerTargetGroups класса IUpdateServer, чтобы получить глобально уникальный идентификатор (GUID) группы компьютеров, для которого утверждаются обновления (в данном случае группа All Computers). В переменную $TargetGroup вводится ссылка на эту группу компьютеров. Затем с помощью метода GetUpdates класса IUpdateServer переменная $updates заполняется коллекцией новейших версий обновлений из базы данных WSUS, в том числе замененных и отклоненных.
Для каждого обновления продукта в этой коллекции сценарий ApproveUpdates.ps1 ищет совпадение в файле RequiredUpdates.txt. Если совпадение обнаружено, обновление записывается в журнал found.log. Затем сценарий проверяет, не истек ли срок действия обновления. Просроченные обновления заносятся в журнал expired.log, остальные отмечаются как утвержденные для установки в службе WSUS. Если эта операция выполняется успешно, сценарий добавляет обновление в журнал approved.log; если она завершается неудачей, обновление вносится в журнал failed.log.
Проверив коллекцию, ApproveUpdates.ps1 сравнивает список обнаруженных обновлений в журнале found.log со списком требуемых обновлений в файле RequiredUpdates.txt. Если обновление присутствует в файле RequiredUpdates.txt, но не в found.log, значит, обновления нет на сервере WSUS. Все отсутствующие обновления записываются в журнал missing.log.
Наконец, сценарий отображает результаты. Их также можно искать в файлах журналов.
Пользователи службы WSUS, желающие опробовать ApproveUpdates.ps1, могут ознакомиться с его кодом в листинге. Сценарий нужно запускать из каталога, в котором расположен файл RequiredUpdates.txt.
М. Самер Савас — системный администратор в компании Datel Systems and Software. Имеет сертификаты MCSE и MCTS, специализируется на работе с Active Directory, развертывании и управлении системами
# FileName: ApproveUpdates.ps1
# Created: [04/26/2010], Author: M.Samer Sawas
# Requirments: -Powershell version 2.0; -Must run on local WSUS server (not remote);
# -Before running this script, change to the directory where the updates text file (RequiredUpdates.txt) is located
# Purpose: Approve updates for install to All Computers group, updates titles are stored in a text file
# When multiple updates have the same title, the script tries to approve all of them verify updates file
if (!(Test-Path -Path RequiredUpdates.txt)) {Write-Host "The updates file RequiredUpdates.txt is not located in the current directory !!!";break}
# Read required updates from file into $ReqUpdatesFile and verify that it's not empty
$ReqUpdatesFile = Get-Content "RequiredUpdates.txt"
if ($ReqUpdatesFile -eq $null) {Write-Host "The updates file is empty !!!";break}
# initialize variables and log files
$UpdatesCount = 0 # all updates in WSUS database
$FailedCount = 0 # updates with failed approval
$ApprovedCount = 0 # updates with succeeded approval
$FoundCount = 0 # matches (required updates found in WSUS database)
$MissingCount = 0 # missing updates (required updates not found in WSUS database)
$ExpiredCount = 0 # required updates found to be expired in WSUS database)
$ApprovalSucceeded = $True
Set-content Found.log $null
Set-Content Missing.log $null
Set-content Failed.log $null
Set-content Approved.log $null
Set-content Expired.log $null
# Load WSUS administration
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.UpdateServices.Administration') | out-null
# Connect to WSUS server
$updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer()
# Get the computer group ID for "All Computers" group
$updateServer.GetComputerTargetGroups() | foreach-object {
if ($_.Name -eq "All Computers") {$TargetGroupID = $_.id;}
}
$TargetGroup = $updateServer.GetComputerTargetGroup($TargetGroupID)
# Get updates from WSUS server
$updates = $updateServer.GetUpdates()
# loop through updates for approval
foreach ($update in $updates)
{
if ($ReqUpdatesFile –contains $update.Title )
{
$FoundCount = $FoundCount + 1
$updateGuid = $update.id.UpdateId # Obtain update GUID
$UpdateTitleAndGUID = [string]::Concat($update.Title,"-GUID:",$updateGuid) # GUID is attached to title to uniquely identify updates
add-content Found.log $UpdateTitleAndGUID # Log found updates
if ($update.PublicationState -eq [Microsoft.UpdateServices.Administration.PublicationState]::Expired)
{ $ExpiredCount = $ExpiredCount + 1;add-content Expired.log $UpdateTitleAndGUID }
else
{
Try{$update.Approve("Install",$TargetGroup) | out-null}
Catch # executes when approval failes
{
$ApprovalSucceeded = $False
add-content Failed.log $([string]::Concat($UpdateTitleAndGUID,", reason:",$($_.Exception.Message)))
add-content Failed.log "------------------------------------"
$FailedCount = $FailedCount + 1
}
Finally {if ($ApprovalSucceeded) {add-content Approved.log $UpdateTitleAndGUID;$ApprovedCount = $ApprovedCount + 1}
else {$ApprovalSucceeded = $True } }
}
}
$UpdatesCount = $UpdatesCount + 1
}
# Find missing updates
foreach ($ReqUpdate in $ReqUpdatesFile)
{
if (!(select-string -path Found.log -pattern $ReqUpdate -quiet -simplematch))
{add-content Missing.log $ReqUpdate;$MissingCount = $MissingCount +1}
}
Function ReportUpdates($count,$state,$LogFile)
{
if ($Count -gt 0)
{
write-host $Count "update(s)" $state ":" -foregroundcolor «yellow»
write-host «===============================================»
Get-Content -path $LogFile | sort-object
write-host
}
else
{
write-host "No updates" $state -foregroundcolor "yellow"
write-host «===============================================»
write-host
}
}
ReportUpdates $MissingCount "Missing from WSUS Database" "missing.log"
ReportUpdates $FoundCount "Found in WSUS Database" "Found.log"
ReportUpdates $FailedCount "failed approval" "Failed.log"
ReportUpdates $ExpiredCount "expired" "expired.log"
ReportUpdates $ApprovedCount "Approved successfully" "Approved.log"
write-host "Total number of updates processed: " $UpdatesCount -foregroundcolor "yellow"
.jpg)