Automating the installation of updates on client machine dropout erroneous updates
Once a year an update of the break the habitual work. Windows tries to deliver it 3 times and if 3 times was roll it loaded without installation. Users morning start to ring. If nothing is done then the next morning the situation repeats.
the
It's all uncomfortable, so the admin is almost always going to do the same thing — he shut off the updates on the problem machine. And in a year or two it will start to roll updates and will stolknetsya with the same problem.
Since bug updates triggers the emergency mode, eats an incredible amount of staff time on completely meaningless garbage, and for the purpose of preached to intelligent infrastructure it was decided to try to automate this process. Along the way was the script which can install all updates on viewstravel the machine in automatic mode.
Immediately I say — this script is not able to repair a system that does not start at all, he knows himself to put updates, to automatically throw out the update, cause cyclic restart, has the ability to manually add bad obnovleniya to the list and to inform the administrator of any problems with the installation.
the source of the article in one file
is 0. Allow execution of scripts in your system. Set-ExecitionPolicy Unrestricted or sign your scripts with a certificate.
1. copy the script WUErrorreporting on the disc controlled machine and add it to task scheduler for example, 12:30 PM. If anyone knows how to create a scheduled job click here
2. Wystawie options alerts on update failures, this will change the settings
$ReportMail1 = 'admin@test.local' your email
$SMTPServer = 'mail.test.local' to your mail server.
3. copy the script to reset the configuration on the right machine and run it. It will create a directory with initial settings if the directory is reset them to initial state.
4. to the directory with the previous script, copy the script updates (note, the below great script, 85кб), not to copy-paste download it otsuda

5. create a job in task scheduler with the rights of the SYSTEM to run 1 time a day. Known issue — installation of updates can only be initiated under the rights SYSTEM. (by the way can this method be used to Zap Article based on information from habrahabr.ru
the
-
the
- On WSUS the server makes no sense to move it to the Unapproved because the patch is already downloaded on the client machine and is located in the folder SoftwareDistribution, need to remove manually the
- buggy patches can be a lot the
- through a floor of year for the administrator to Park it again to approve the
- welcome again in six months or a year, sifting good from bad is to 1 day work for 1 car (class) the
- updates one configuration may not be suitable for other configuration even if the OS one the
- update status hidden will be reset if you delete the SoftwareDistribution
SoftwareDistribution have to fold if glyuknul base too long searching, but better to do it periodically
It's all uncomfortable, so the admin is almost always going to do the same thing — he shut off the updates on the problem machine. And in a year or two it will start to roll updates and will stolknetsya with the same problem.
Since bug updates triggers the emergency mode, eats an incredible amount of staff time on completely meaningless garbage, and for the purpose of preached to intelligent infrastructure it was decided to try to automate this process. Along the way was the script which can install all updates on viewstravel the machine in automatic mode.
Immediately I say — this script is not able to repair a system that does not start at all, he knows himself to put updates, to automatically throw out the update, cause cyclic restart, has the ability to manually add bad obnovleniya to the list and to inform the administrator of any problems with the installation.
How it all start, quick start
the source of the article in one file
is 0. Allow execution of scripts in your system. Set-ExecitionPolicy Unrestricted or sign your scripts with a certificate.
1. copy the script WUErrorreporting on the disc controlled machine and add it to task scheduler for example, 12:30 PM. If anyone knows how to create a scheduled job click here
WUErrorreporting.ps1
<#
2016.05.23
Windows Update Error reporter
semaphoric about waznych problems on the client. Inspects the installation log and if
there is an event 20 forms administrative letter.
Pak N. V.
#>
#############
# Variables #
#############
# the number of days for which to view the magazine
[int]$DaysBefore = 5
# whether to preserve the list is not steady updates and where
$SaveLog = $false
$LogPath = 'c:\WUError.txt'
# save the HTML report
[boolean]$SaveReport = $False
[string]$ReportPath = 'C:\WUErrorReport.html'
# send the HTML report
[boolean]$SendReport = $true
[string]$ReportMail1 = 'admin@test.local'
[string]$from = 'bot_abormot@test.local'
[string]$SMTPServer = 'mail.test.local'
#############################################################################
# get the events for the last day
$Events = Get-EventLog-LogName System -EntryType Error-After (Get-Date).AddDays(-$DaysBefore) -InstanceId 20 -ErrorAction SilentlyContinue
# if there was obliki install prodoljaem processing, otherwise exit
if ($Events.Count-eq 0)
{
Write-Host 'error installing updates there, completing the script' -ForegroundColor Green
Exit
}
# container for events
$Log = @()
# pereberia events and take out the numbers of the updates with installation errors
foreach ($Event in $Events)
{
$regex = $Event.Message-match "KB\d+"
$KB = $matches[0]
$params = [ordered]@{ 'KB'=$KB
#'EntryType'=$Event.EntryType
'Index'=$Event.Index
'MachineName'=$Event.MachineName
'Message'=$Event.Message
'Source'=$Event.Source
'TimeGenerated'=$Event.TimeGenerated
'TimeWritten'=$Event.TimeWritten
'UserName'=$Event.UserName
}
$obj = New-Object -TypeName PSObject -Property $params
$Log += $obj
}
if ($SaveLog -eq $true)
{
# save the list of updates with errors
$Log | select-ExpandProperty KB | Add-Content -Path $LogPath
}
#worked below to send an email
################################# beautiful report #####################################
Write-Verbose 'producing HTML fragment'
$ClientName = $env:COMPUTERNAME
$TotalErrors = $log.Count
$frag1 = $Log | ConvertTo-Html -As table-Fragment-PreContent "<h2>Windows Update error report. $ClientName </h2><br><h3>Total $TotalErrors errors.</h3>" | Out-String
Write-Verbose 'definiting CSS'
$head = @'
<style>
body { background-color:#ffffff;
font-family:Tahoma;
font-size:12pt; }
td, th { border:1px solid black;
border-collapse:collapse; }
th { color:white;
background-color:black; }
table, tr, td, th { padding: 2px; margin: 0px }
table {
font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif;
font-size: 14px;
border-radius: 10px;
border-spacing: 0;
text-align: center;
}
th {
background: #BCEBDD;
color: white;
text-shadow: 0 1px 1px #2D2020;
padding: 10px 20px;
}
th, td {
border-style: solid;
border-width: 0 1px 1px 0;
border-color: white;
}
th:first-child, td:first-child {
text-align: left;
}
th:first-child {
border-top-left-radius: 10px;
}
th:last-child {
border-top-right-radius: 10px;
border-right: none;
}
td {
padding: 10px 20px;
background: #F8E391;
}
tr:last-child td:first-child {
border-radius: 0 0 0 10px;
}
tr:last-child td:last-child {
border-radius: 0 0 10px 0;
}
tr td:last-child {
border-right: none;
}
</style>
'@
$Date = Get-Date
if ($SendReport -eq $true)
{
Write-Verbose 'SendEmail'
$encoding = [System.Text.Encoding]::UTF8
$body = ConvertTo-HTML -head $head-PostContent $frag1 -PreContent "<h1>Windows Update error report. Client $ClientName. Date:$Date</h1>" | Out-String
$params = @{'To'=$ReportMail1
'From'=$from
'Subject'="$ClientName. Windows Update error $Date"
'Body'=$Body
'BodyAsHTML'=$True
'SMTPServer'=$SMTPServer}
Send-MailMessage @params -Encoding $encoding
}
2. Wystawie options alerts on update failures, this will change the settings
$ReportMail1 = 'admin@test.local' your email
$SMTPServer = 'mail.test.local' to your mail server.
3. copy the script to reset the configuration on the right machine and run it. It will create a directory with initial settings if the directory is reset them to initial state.
Rearm_Install-ClientUpdate.ps1
<#
resets the variables of the machines for the first use
#>
# path to the directory where the working files of the module
$Path = Split-Path ($MyInvocation.MyCommand.Path) -Parent
if ((Test-Path -Path "$Path\BadUpdates") -eq $false)
{
New-Item -Path "$Path\BadUpdates" -ItemType Directory -Force
}
# the last installed updates
$LastInstalledUpdatesFile = "$Path\BadUpdates\LastInstalledUpdates.txt"
# a list of really bad updates
$BadUpdatesFile = "$Path\BadUpdates\BadUpdates.txt"
# FastInstaller
$KAFUFile = "$Path\BadUpdates\KAFU.txt"
# Speed install updates at a time
$KAFUDeltaFile = "$Path\BadUpdates\KAFUDelta.txt"
# Fastinstaller watchdog
$KAFUWatchDogFile = "$Path\BadUpdates\KAFUWatchDog.txt"
# Fastinstaller update installer watchdog
$KAFUWatchDog2File = "$Path\BadUpdates\KAFUWatchDog2.txt"
# SlowInstaller
$KASUFile = "$Path\BadUpdates\KASU.txt"
# file log
$WorkLogFile = "$Path\BadUpdates\log.txt"
# General machine
$KAFile = "$Path\BadUpdates\KA.txt"
Set-Content $LastInstalledUpdatesFile -Value "
Set-Content $KAFUFile -Value 0
Set-Content $KAFUDeltaFile -Value 5
Set-Content $KAFUWatchDogFile -Value 0
Set-Content $KAFUWatchDog2File -Value 0
Set-Content $KASUFile -Value 0
Set-Content $KAFile -Value 99
Set-Content $BadUpdatesFile -Value "
4. to the directory with the previous script, copy the script updates (note, the below great script, 85кб), not to copy-paste download it otsuda

Install-ClientUpdate.ps1
<#
2016.06.14
ver 2
installs the updates on client machines trying to identify the updates causing
brake when loading. Was done to reduce stress on the Department system administrators.
maybe
to ustanavlivat quickly many updates in batches (FastUpdate) in a fast pass puts you first by 30%
over time, if not get the 25%, if not get the 5 at a time.
to put one obnovleniyu, and after the passage of all those that did not add up to the list of bad
if I add to the list bad the next time you work these updates will be ignored regardless
from what they approved on the upstream server or not
resets agent was on the machine at every startup, you can reset glitches, or curves updates
for use as robot updates
1. select the directory where will write the script
2. write to file "\BadUpdates\KA.txt" the number is greater than 9, for example 11
3. create task scheduler from admin job rights system
trigger - system starts to wait 6 hours
action - start a program powershell.exe -file "your path to script\Install-ClientUpdate.ps1"
5. write in the script your settings
install $RebootEnabled = $False
what address to send the alert about bad updates and do I need to send
to automatically install many updates.
1. select the directory where will write the script
2. write to file "\BadUpdates\KA.txt" the number is greater than 9, for example 11
3. create task scheduler from admin job rights system
trigger - at startup (when you turn on the computer) to postpone for 10 minutes
action - start a program powershell.exe -file "your path to script\Install-ClientUpdate.ps1"
4. enable scripting in your environment
5. write in the script your settings
install $RebootEnabled = $true
what address to send the alert about bad updates and do I need to send
glitches:
in some cases, not removed the SoftwareDistribution folder. this occurs because each process is holding the folder
basically it creates a directory in the Plugins subfolder. in this case, you need reboots and once to empty the folder manually.
in the code, the amendment is made to the script didn't stop in that case, just clean it at the max and restart the service
without completing.
The user sometimes gmake shutdown to "Install updates and shut down" which causes the installation of all General
updates. Need to explain what dostatochno only to finish the job and show you how. Otherwise you need to add the part
setting IsHidden=1 for all updates except those that are selected for installation in this session.
probably freeze updates if the setting "4. automatically install updates and reboot the computer."
you need to put a different setup.
possible glitch on win 7 if the update source is the world. The script never can finish getting the updates
consistently works with local, WSUS
requires:
powershell 2.0
Pak Nikolay
GEOM, Aqtobe
tested on win 8.1/2012R2; win 7; win 2008R2
#>
#############
# Variables #
#############
# Allow reboot. setting this flag causes a restart after each operation. need if you need to put
# a lot of upgrades on the car. set the scheduler time after running 10 minutes, and allow the reboot. the script itself will be
# install updates for you.
#$RebootEnabled = $true
$RebootEnabled = $False
# Fast install if more than this threshold then go to quick setup
$FastInstallLimit = 45
# path to the directory where the working files of the module
$Path = Split-Path ($MyInvocation.MyCommand.Path) -Parent
# the last installed updates
$LastInstalledUpdatesFile = "$Path\BadUpdates\LastInstalledUpdates.txt"
# a list of really bad updates
$BadUpdatesFile = "$Path\BadUpdates\BadUpdates.txt"
# FastInstaller
$KAFUFile = "$Path\BadUpdates\KAFU.txt"
# Speed install updates at a time
$KAFUDeltaFile = "$Path\BadUpdates\KAFUDelta.txt"
# Fastinstaller watchdog
$KAFUWatchDogFile = "$Path\BadUpdates\KAFUWatchDog.txt"
# Fastinstaller update installer watchdog
$KAFUWatchDog2File = "$Path\BadUpdates\KAFUWatchDog2.txt"
# SlowInstaller
$KASUFile = "$Path\BadUpdates\KASU.txt"
# file log
$WorkLogFile = "$Path\BadUpdates\log.txt"
# General machine
$KAFile = "$Path\BadUpdates\KA.txt"
########################## Report params ###################################
[boolean]$SaveReport = $true
[string]$ReportPath = 'C:\Report-InstallUpdates.html'
[boolean]$SendReport = $true
[string]$From = 'bot_abormot@test.local'
[string]$SMTP = 'mail.test.local'
[string]$ReportMail1 = 'admin1@test.local'
[string]$ReportMail2 = 'admin2@test.local'
[string]$ReportMail3 = 'admin3@test.local'
function report
{
Param ( [string]$Text = 'test' )
$Date = Get-Date
if ($SaveReport = $true)
{
$Text | Out-File $ReportPath
}
if ($SendReport = $true)
{
$encoding = [System.Text.Encoding]::UTF8
$body = $Text
$Subj = "install-updates script report $Date"
$params = @{'To'=$ReportMail1
'From'=$From
'Subject'=$Subj
'Body'=$Body
'BodyAsHTML'=$True
'SMTPServer'=$SMTP}
Send-MailMessage @params -Encoding $encoding
$params = @{'To'=$ReportMail2
'From'=$From
'Subject'=$Subj
'Body'=$Body
'BodyAsHTML'=$True
'SMTPServer'=$SMTP}
Send-MailMessage @params -Encoding $encoding
$params = @{'To'=$ReportMail3
'From'=$From
'Subject'=$Subj
'Body'=$Body
'BodyAsHTML'=$True
'SMTPServer'=$SMTP}
Send-MailMessage @params -Encoding $encoding
}
}
########################## Report params ###################################
function Log
{
PARAM ( [parameter(Mandatory = $true)]
[string]$Message
)
$Date = Get-Date-Format "yyyy.MM.dd HH:mm:ss"
[string]$Msg = $Date + "`t" + $Message
Out-File -FilePath $WorkLogFile -InputObject $Msg -Append # -encoding unicode
}
function Clear-Log
{
$Date = Get-Date-Format "yyyy.MM.dd HH:mm:ss"
$Msg = $Date + "`t" + 'log cleared by calling Clear-Log'
}
function Trim-Log
{
# if the log is greater than 5 megabytes kilinochi log
if ( (Get-Item-Path $WorkLogFile).Length-gt 5mb )
{
Clear-Log
}
}
<#
reset the SoftwareDistribution folder
often the update service can not be updated, an error, or crookedly works
helps reset service WUAUSRV in particular to delete the folder with its settings.
at the start she would make it again
#>
function ResetSoftwareDistribution
{
$WUServices = 'BITS'and'wuauserv'
$windows = 0x24
Log 'call ResetSoftwareDistribution'
Log 'stopping WU services'
Write-Host "reset SoftwareDistribution" -ForegroundColor Green
Write-Host "-------------------------------" -ForegroundColor Green
Write-Host "stopping services" -ForegroundColor Green
$WUServices | Stop-Service -Verbose
Start-Sleep -Seconds 20
# if the service is stopped then continue
if ( ((Get-Service 'BITS').Status-eq 'stopped' ) -and ((Get-Service 'wuauserv').Status-eq 'stopped') )
{
Log 'services stopped sucsessful'
Write-Host 'service was stopped continue' -ForegroundColor Green
$Folders = Get-ChildItem ( (New-Object -ComObject Shell.Application).Namespace( $windows ).Self.Path) -Directory | where { $_.Name-like '*SoftwareDistribution*' }
Write-Host "the folder service WU" -ForegroundColor Green
$Folders
Write-Host "delete ..."
$Folders | Remove-Item -Recurse -Force -Verbose -Confirm:$false
# check removal
$Folders = Get-ChildItem ( (New-Object -ComObject Shell.Application).Namespace( $windows ).Self.Path) -Directory | where { $_.Name-like '*SoftwareDistribution*' }
if ($Folders -eq $null)
{
Log 'SoftwareDistribution folder deleted successful'
Write-Host "deleting SoftwareDistribution successfully" -ForegroundColor Green
}
else
{
Log 'deleted SoftwareDistribution folder NOT successful'
Write-Host "SoftwareDistribution wasn't deleted!" -ForegroundColor Red
# if you raskomentiruyte the operator below it is possible to hung if the idea of garbage blocks the deletion Softwaredistrib
#Exit
}
}
Log 'WU starting services'
Write-Host "startup services" -ForegroundColor Green
$WUServices | Start-Service -Verbose
}
<#
downloads and installs these updates
upgrade installation passed list of KB numbers
only looks for updates with the IsHidden flag is equal to 0, if you reset the Softwaredistribution
reset all Hidden updates.
Theoretically, for beauty it is necessary to screw to it to set IsHidden = 1 for all updates
except that stavte at the moment
example call
'2976978', '3156418' | install-updates -Verbose
#>
function install-updates
{
[CmdletBinding()]
PARAM (
[Parameter( Position=0,
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[string[]]$KB
)
BEGIN
{
Log 'call install-updates'
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$Updates = $searcher.Search("IsInstalled=0 and Type='Software' and ISHidden=0")
# platoon flag whether an update is available
if ($Updates.Updates.Count-eq 0) { $NoUpdates = $true } else { $NoUpdates = $false }
# diagnostic output
Write-Verbose '---------------------------------------------------------------------'
Write-Verbose "install-updates: status variable NoUpdates = $NoUpdates"
if ($NoUpdates -eq $false)
{
Write-Verbose "found updates waiting to be installed"
$temp1 = $Updates.updates | select Title
$temp1 | Write-Verbose
$Count = $Updates.Updates.Count
Write-Verbose "$Count updates awaiting installation"
Log "$Count updates awaiting installation"
foreach ( $temp in $temp1 ) { Log "$temp" }
}
else
{
Log "install-updates: updates to install was not found "
Write-Verbose "install-updates: updates to install was not found "
}
Write-Verbose '---------------------------------------------------------------------'
}
PROCESS
{
Write-Verbose "install-updates: passed parameter in the process block $KB"
if ($NoUpdates -eq $true) { break }
if ($KB-match '' ) { break }
$HotFix = $Updates.Updates | where { $_.Title -like "*$KB*" }
if ($HotFix-eq $null)
{
Write-Verbose "passed for the installation of the update was not found"
Log "submitted for the installation of the update was not found"
break
}
else
{
$Title = $HotFix.Title
Write-Verbose "found upgrade to install $Title"
Log "found upgrade to install $Title"
}
# download the updates
$downloads = New-Object -ComObject Microsoft.Update.UpdateColl
$downloads.Add( $HotFix )
# in this place known error 80070005. This operation can only be run with SYSTEM rights
# if you see this error then create a task scheduler job to run this script with the rights systems
# and call itself the task itself
Write-Verbose 'download the update'
Log 'download update'
$downloader = $session.CreateUpdateDownLoader()
$downloader.Updates = $downloads
$downloader.Download()
{
Log 'download successfull'
Write-Verbose 'update downloaded. (located in the downloads folder)'
}
$installs = New-Object -ComObject Microsoft.Update.UpdateColl
if ($HotFix.IsDownloaded)
{
$installs.Add( $HotFix ) | Out-Null
}
log 'start instal'
# in this place known error 80070005. This operation can only be run with SYSTEM rights
# if you see this error then create a task scheduler job to run this script with the rights systems
# and call itself the task itself
$installer = $session.CreateUpdateInstaller()
$installer.Updates = $installs
$installresult = $installer.Install()
$installresult
log 'installing successfull'
}
END
{
Write-Verbose 'install-updates: worked install updates'
log 'install-updates: worked install updates'
log '--------------------------------------------------------------'
}
}
<#
use this function if you need to put more than 20-30 updates
quickly puts a bunch of updates. does not control updates.
designed for fast rolling upgrades when you need to install a lot of updates
and winnowing out the good from the bad. has its own variables
The user does not have a long time is under the operation of this function, since rolling 10-20 updates
and rollback in case of error, will not allow him to work an hour and a half after each operation.
it can be used only once, and it is desirable to explain to the user why in the morning he will have
the long wait for the rollback of updates.
before entering the procedure you need to set $KAFUWatchDog to zero
if 0 it means that when you pass 1/3 to each portion was erroneous obnovleniyu
if there is 1 it means that when you pass in increments of 1/4 per serving was erroneous obnovleniyu
if it's 2 it means when you pass in increments of 5 pieces per serving was erroneous obnovleniyu
#>
# Status
[int]$KAFU = Get-Content $KAFUFile
# Speed install updates at a time
[int]$KAFUDelta = Get-Content $KAFUDeltaFile
function Fast-Update
{
function Write-KAFU
{
PARAM ( $State )
Set-Content $KAFUFile -Value $State
}
Log "--- Fast-Update ---------------------------------------------------------"
Log "Fast-Update run quick setup"
switch ($KAFU)
{
0 {
Log "logged in state 0"
# calculated the speed with which we do pass
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$temp = $searcher.Search("IsInstalled=0 and Type='Software'" )
$Count = $temp.Updates.Count
# watch watch dog, if the passage does not mean the first was fail and need to lower the speed of installing updates
$KAFUWatchDog = Get-Content $KAFUWatchDogFile
log "KAFUWatchDog = $KAFUWatchDog"
switch ($KAFUWatchDog)
{
0 { # default parameter, divide the number of updates by 2 and take the number as step
$KAFUDelta = [Math]::Truncate( $Count / 3 )
Log "first entry, set the step to 1/3 the amount and is $KAFUDelta"
}
1 { # divide the number of updates by 4 and take the number as step
$KAFUDelta = [Math]::Truncate( $Count / 4 )
Log "first entry, set the step to 1/4 of the quantity and is equal to $KAFUDelta"
}
2 { # we have a specific glitches in each of the four packs was mistakenly updates
# set to 5 updates at a time
$KAFUDelta = 5
log 'we have specific bugs in each of the four batches was in error update set 5'
}
default { Log 'unknown status watch dog is discharged to zero'
$KAFUWatchDog = 0
$KAFUDelta = [Math]::Truncate( $Count / 3 )
Set-Content $KAFUWatchDogFile -Value $KAFUWatchDog
}
}
# reset the list before work
Set-Content $LastInstalledUpdatesFile -Value "
Set-Content $KAFUDeltaFile -Value $KAFUDelta
Set-Content $KAFUWatchDog2File -Value 0
Write-KAFU 1
break
}
1 {
Log "enter in state 1"
$LastInstalled = Get-Content $LastInstalledUpdatesFile
$BadUpdates = Get-Content $BadUpdatesFile
log 'get the list of updates from the upstream server'
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$temp = $searcher.Search("IsInstalled=0 and Type='Software'" )
$Updates = $temp.Updates | select title
# make a list of updates to install by the numbers
[string[]]$HotFixs = "
foreach ($temp in $Updates)
{
$regex = $temp.Title-match "KB\d+"
$KB = $matches[0]
Log "found upgrade to install: $KB"
}
$Count = $HotFixs.Count
Log "all updates to install $Count"
log 'clean list'
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$Upd
# throw away those that tried to put and known bad
if ($BadUpdates.Count-ne 0)
{
$temp = Compare-Object-ReferenceObject $HotFixs -DifferenceObject $BadUpdates
$temp = $temp | where { $_.Sideindicator -like '<=' } | select-ExpandProperty InputObject
$HotFixs = $temp
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$HotFixs = $Upd
$temp = $HotFixs
Log "after exclusion of bad updates left:"
foreach ( $temp1 in $temp ) { Log "after exclusion of bad updates left: $temp1" }
$Count = $temp.Count
Log "total: $Count pieces"
}
else
{
Log "known bad updates, no"
}
if ($LastInstalled.Count-ne 0)
{
$temp = Compare-Object-ReferenceObject $HotFixs -DifferenceObject $LastInstalled
$temp = $temp | where { $_.Sideindicator -like '<=' } | select-ExpandProperty InputObject
$HotFixs = $temp
Log "after exclusion of those that tried it left:"
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$HotFixs = $Upd
$temp = $HotFixs
foreach ( $temp1 in $temp ) { Log "after exclusion of those that I tried left: $temp1" }
$Count = $temp.Count
Log "total: $Count pieces"
}
else
{
Log "no more did not set up this"
}
# check watch dog installer
[int]$KAFUWatchDog2 = Get-Content $KAFUWatchDog2File
if ($KAFUWatchDog2 -gt 20)
{
Log "load watch dog installer, looks like we're stuck at 1 forced reset: $KAFUWatchDog2"
Write-KAFU 2
Set-Content $KAFUWatchDog2File -Value 0
break
}
if ($HotFixs.Count-eq 0)
{
# aisle over
log 'passage over, updates left. go to state 2'
Write-KAFU 2
break
}
else
{
# select the updates to install
$temp = $HotFixs | select -First $KAFUDelta
$Count = $temp.Count
if ($Count -eq 0)
{
log 'no remaining updates. go to state 2'
Write-KAFU 2
break
}
foreach ( $temp1 in $temp ) { Log "is selected on the installation: $temp1" }
Log "total: $Count pieces"
$HotFixs = $temp
# save the list
Add-Content -Path $LastInstalledUpdatesFile -Value "
Add-Content -Path $LastInstalledUpdatesFile -Value $HotFixs
@(Get-Content $LastInstalledUpdatesFile) -match '\S' | out-file $LastInstalledUpdatesFile
LOG "kept a list of updates to install"
# sent to the installation
log 'starting install updates'
$HotFixs | install-updates
}
Set-Content $KAFUWatchDog2File -Value ($KAFUWatchDog2 + 1)
break
}
2 { # analyze the passage if the permanent error reduce speed and try again
Log 'included in condition 2.'
$KAFUWatchDog = Get-Content $KAFUWatchDogFile
$KAFUDelta = Get-Content $KAFUDeltaFile
$LastInstalled = Get-Content $LastInstalledUpdatesFile
log "KAFUWatchDog = $KAFUWatchDog"
switch ($KAFUWatchDog)
{
0 {
# the first of the States. The passage was successful? The resulting list is not set updates
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$temp = $searcher.Search("IsInstalled=0 and Type='Software'" )
$Updates = $temp.Updates
# the number of remaining updates is less than Delta * 3 - 2
$Count1 = $Updates.Count
if ($KAFUDelta -eq 0) { $KAFUDelta = 5 }
$Count2 = $KAFUDelta * 3 - 2
if ($Count2 -lt $Count1)
{
# does not install any of the updates. Reduce speed install updates
$KAFUWatchDog = 1
Set-Content $KAFUWatchDogFile -Value 1
Write-KAFU 0
Log 'not installed any of the updates. vach dog = 1. go to 0'
break
else
{
log quick the installation was successful WatchDog = 0'
log', go to state 3'
Write-KAFU 3
break
}
}
1 {
# check how much of what you pulled
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$temp = $searcher.Search("IsInstalled=0 and Type='Software'" )
$Updates = $temp.Updates | select title
# the number of remaining updates is less than Delta * 3 - 2
$Count1 = $Updates.Count
$Count2 = $KAFUDelta * 4 - 2
if ($Count2 - > $Count1)
{
# we have an epic crap - bad 4 hotfix evenly smearing each of 25% of the updates
# reduce speed install updates to 5
$KAFUWatchDog = 2
Set-Content $KAFUWatchDogFile -Value 2
Write-KAFU 0
Log 'not installed any of the updates. wachdog = 2. go to 0'
break
}
else
{
log quick the installation was successful WatchDog = 1'
log', go to state 3'
Write-KAFU 3
break
}
}
2 { # we worked the install 5 updates at a time
log quick the installation was successful WatchDog = 2'
log', go to state 3'
Write-KAFU 3
break
}
default { Log 'unknown state reset to 0 watchdog'
Set-Content $KAFUWatchDogFile -Value 0
Write-KAFU 0
break
}
}
}
3 { # finished, cyclessa
Write-KAFU 3
break
}
default {
Set-Content $KAFUWatchDogFile -Value 0
Write-KAFU 0
Log "warning!!! an unknown state ON, reset to 0. KAFU = $KAFU"
break
}
}
Log "--- Fast-Update -- worked-------------------------------------------------------"
}
<################################################################################################
we can add two upgrades for passage.
most of sadasya function in relation to the user.
It is used to accelerate the installation of updates, put a pair in a single pass.
if updates will be 48 on the installation of all will take 24 days at 2 per day that is
1 month. With small updates to the user will take 3-6 minutes a day, if refreshed
large then 30-40 minutes in the event of a failure.
################################################################################################>
<#
installs updates one by one with a throw into the sheet bad updates
a Central feature around which everything revolves
thanks to this function we can do the work almost automatically
#>
# Status
[int]$KASU = Get-Content $KASUFile
function Slow-update
{
function Write-KASU
{
PARAM ( $State )
Set-Content $KASUFile -Value $State
}
Log "--- Slow Update ---------------------------------------------------------"
Log "Slow Update start"
switch ($KASU)
{
0 {
# install one of the updates
log "Went to 0, making the original settings"
# reset the list before work
Set-Content $LastInstalledUpdatesFile -Value "
Set-Content $KAFUWatchDog2File -Value 0
Set-Content $KAFUWatchDog2File -Value 0
Write-KASU 1
break
}
1 {
log "Entered sostoianie 1"
$LastInstalled = Get-Content $LastInstalledUpdatesFile
$BadUpdates = Get-Content $BadUpdatesFile
log 'get the list of updates from the upstream server'
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$temp = $searcher.Search("IsInstalled=0 and Type='Software'" )
$Updates = $temp.Updates | select title
# make a list of updates to install by the numbers
[string[]]$HotFixs = "
foreach ($temp in $Updates)
{
$regex = $temp.Title-match "KB\d+"
$KB = $matches[0]
$HotFixs += $KB
Log "found upgrade to install: $KB"
}
$Count = $HotFixs.Count
Log "all updates to install $Count"
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$PotentialBad = $Upd
# throw away those that tried to put and known bad
{
$temp = Compare-Object-ReferenceObject $HotFixs -DifferenceObject $BadUpdates
$temp = $temp | where { $_.Sideindicator -like '<=' } | select-ExpandProperty InputObject
$HotFixs = $temp
Log "after exclusion of bad updates left:"
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$HotFixs = $Upd
$temp = $HotFixs
foreach ( $temp1 in $temp ) { Log "after exclusion of bad updates left: $temp1" }
$Count = $temp.Count
Log "total: $Count pieces"
}
else
{
Log "known bad updates, no"
}
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$HotFixs = $Upd
if ($LastInstalled.Count-ne 0)
{
$temp = Compare-Object-ReferenceObject $HotFixs -DifferenceObject $LastInstalled
$temp = $temp | where { $_.Sideindicator -like '<=' } | select-ExpandProperty InputObject
$HotFixs = $temp
Log "after exclusion of those that tried it left:"
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$HotFixs = $Upd
$temp = $HotFixs
foreach ( $temp1 in $temp ) { Log "after exclusion of those that I tried left: $temp1" }
$Count = $temp.Count
Log "total: $Count pieces"
}
else
{
Log "no more did not set up this"
}
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$HotFixs = $Upd
if ($HotFixs.Count-eq 0)
{
# aisle over
log 'passage over, updates left. all not installed potentially bad'
if ($PotentialBad -ne 0 )
{
foreach ( $Bad in $PotentialBad )
{
log "probably a bad update: $Bad"
}
# leave here because the function is not standalone edition, the report and add in the poor must make higher
#Add-Content -Path $BadUpdatesFile -Value "
#Add-Content -Path $BadUpdatesFile -Value $LastInstalled
}
Write-KASU 2
break
}
else
{
# select the updates to install
$temp = $HotFixs | select -First 1
$Count = $temp.Count
if ( $Count -eq 0 )
{
log', go to state 2'
Write-KASU 2
break
}
foreach ( $temp1 in $temp ) { Log "is selected on the installation: $temp1" }
Log "total: $Count pieces"
$HotFixs = $temp
# save the list
Add-Content -Path $LastInstalledUpdatesFile -Value "
Add-Content -Path $LastInstalledUpdatesFile -Value $HotFixs
@(Get-Content $LastInstalledUpdatesFile) -match '\S' | out-file $LastInstalledUpdatesFile
LOG "kept a list of updates to install"
# sent to the installation
log 'starting install updates'
Write-Host $HotFixs -ForegroundColor Green
$HotFixs | install-updates
}
Set-Content $KAFUWatchDog2File -Value ($KAFUWatchDog2 + 1)
break
}
2 {
# exited cyclise
Write-KASU 2
break
}
default {
# unknown state
log "status unknown"
Write-KASU 0
}
}
Log "--- Slow-Update -- worked-------------------------------------------------------"
}
[int]$KA = Get-Content $KAFile
function Write-KA
{
PARAM ( $State )
Set-Content $KAFile -Value $State
}
Log ' '
Log " "
Log ' '
Log ' '
Log ' '
Log '##############################'
Log "### --- start --- ###"
Log '##############################'
switch ($KA)
{
0 { # we start
log( 'KA = 0. Reset all variables and go to wait state updates' )
Set-Content $LastInstalledUpdatesFile -Value "
Set-Content $KAFUWatchDogFile -Value 0
Set-Content $KASUFile -Value 0
Set-Content $KAFUFile -Value 0
Write-KA 9
break
}
1 { # set update
Log 'Condition KA 1. Move fast to install updates'
[int]$KAFU = Get-Content $KAFUFile
if ($KAFU -eq 3)
{
# fast installation is over
log 'quick install worked, go to the slow setting'
Write-KA 2
Set-Content $KASUFile -Value 0
break
}
else
{
log 'call fast octnovdec'
ResetSoftwareDistribution
Fast-Update
Trim-Log
break
}
}
2 { # worked
log 'state 2, slow setting'
[int]$KASU = Get-Content $KASUFile
if ($KASU -eq 2)
{
# worked slow installation
# make a report to the administrator that the testing is over and the updates need to check and possibly perensti group bad
Trim-Log
ResetSoftwareDistribution
log( 'KA = 2. Worked slow installation of updates' )
$BadUpdates = Get-Content $BadUpdatesFile
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$temp = $searcher.Search("IsInstalled=0 and Type='Software'" )
$Updates = $temp.Updates | select title
# make a list of updates to install by the numbers
[string[]]$HotFixs = "
foreach ($temp in $Updates)
{
$regex = $temp.Title-match "KB\d+"
$KB = $matches[0]
$HotFixs += $KB
Log "found upgrade to install: $KB"
}
$Count = $HotFixs.Count
Log "all updates to install $Count"
$PotentialBad = $HotFixs
# discard known bad
if ($BadUpdates.Count-ne 0)
{
$temp = Compare-Object-ReferenceObject $HotFixs -DifferenceObject $BadUpdates
$temp = $temp | where { $_.Sideindicator -like '<=' } | select-ExpandProperty InputObject
$HotFixs = $temp
Log "after exclusion of bad updates left:"
foreach ( $temp1 in $temp ) { Log "after exclusion of bad updates left: $temp1" }
$Count = $temp.Count
Log "total: $Count pieces"
}
else
{
Log "known bad updates, no"
}
$Updates = @()
foreach ($temp in $HotFixs)
{
if ($temp ne ") { $Updates += $temp }
}
if ($Updates.Count-ne 0)
{
# we send an administrative alert
log 'send an administrative alert, and add updates with the list of bad'
Add-Content -Path $BadUpdatesFile -Value "
Add-Content -Path $BadUpdatesFile -Value $Updates
$Date = Get-Date
$CompName = $env:COMPUTERNAME
$body = "<H1>completed installing updates on the computer $CompName,<br><br> likely problematic update</H1><h3>"
foreach ($upd in $updates)
{ $body += "<br> $upd<br>" }
$body += "<br>they added to the list of bad and more will not be installed. check them out in advance, perhaps among them the update approved yesterday or today"
report-text $body
}
Write-KA 9
break
}
else
{
log 'update is not delivered we put one update and fall asleep'
ResetSoftwareDistribution
Trim-Log
Slow-update
break
}
}
9 { # I like to see the updates
log( 'KA = 9. Waiting for updates to install' )
Trim-Log
ResetSoftwareDistribution
$BadUpdates = Get-Content $BadUpdatesFile
log 'get updates from the upstream server'
$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()
$temp = $searcher.Search("IsInstalled=0 and Type='Software'" )
$Updates = $temp.Updates | select title
# make a list of updates to install by the numbers
[string[]]$HotFixs = "
foreach ($temp in $Updates)
{
$regex = $temp.Title-match "KB\d+"
$KB = $matches[0]
$HotFixs += $KB
Log "found upgrade to install: $KB"
}
$Count = $HotFixs.Count
Log "all updates to install $Count"
$PotentialBad = $HotFixs
# discard known bad
if ($BadUpdates.Count-ne 0)
{
$temp = Compare-Object-ReferenceObject $HotFixs -DifferenceObject $BadUpdates
$temp = $temp | where { $_.Sideindicator -like '<=' } | select-ExpandProperty InputObject
$HotFixs = $temp
Log "after exclusion of bad updates left:"
$Upd = @()
foreach ($temp in $HotFixs) { if ($temp ne ") { $Upd += $temp } }
$HotFixs = $Upd
$temp = $HotFixs
foreach ( $temp1 in $temp ) { Log "after exclusion of bad updates left: $temp1" }
$Count = $temp.Count
Log "total: $Count pieces"
}
else
{
Log "known bad updates, no"
}
log 'clean list'
$Updates = @()
foreach ($temp in $HotFixs)
{
if ($temp -ne ")
{ $Updates += $temp }
}
$Count = $Updates.Count
Log "All updates $Count switchable installer"
# if update is more than $FastInstallLimit run quick setup
{
# put the updates quickly
log "updates more than $FastInstallLimit. Go to FastInstall"
Write-KA 1
break
}
if ($Updates.Count-gt 0)
{
log "Go Slow to Install"
Write-KA 2
Set-Content $KASUFile -Value 0
break
}
if ($Updates.Count-eq 0)
{
log 'there are no updates waiting for updates'
Write-KA 9
break
}
}
default { # unknown state
log( 'unknown state of the main machine. go to state 0' )
Write-KA 0
}
}
#ResetSoftwareDistribution
#Fast-Update
#Trim Log
#Slow-update
Log '##############################'
Log "### --- We spent --- ###"
Log '##############################'
if ( $RebootEnabled -eq $true )
{
Restart-Computer -Force
Log 'reboot >>>'
}
<#
schtasks /run /tn "\My_Tasks\PSWindowsUpdate"
[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("cp866")
#>
5. create a job in task scheduler with the rights of the SYSTEM to run 1 time a day. Known issue — installation of updates can only be initiated under the rights SYSTEM. (by the way can this method be used to Zap Article based on information from habrahabr.ru
Комментарии
Отправить комментарий