-
Notifications
You must be signed in to change notification settings - Fork 0
/
Check-WindowsUpdates.ps1
260 lines (230 loc) · 11.7 KB
/
Check-WindowsUpdates.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
<#
.Synopsis
Print the Microsoft auto-update settings for the local computer
and optionally list pending updates.
Copyright (c) 2016 by MCB Systems. All rights reserved.
Free for personal or commercial use. May not be sold.
No warranties. Use at your own risk.
.Notes
Name: MCB.WindowsUpdate.ShowSettings.ps1
Author: Mark Berry, MCB Systems
Created: 10/03/2014
Last Edit: 08/04/2016
Adapted from http://fixitscripts.com/problems/windows-update-settings.
Also see https://technet.microsoft.com/en-us/library/ee692834.aspx
http://powershellautomation.blogspot.com/2013/05/list-installed-pending-updates.html
Changes:
10/10/2014 - Reformat fixed output to be narrower.
03/12/2015 - Rename script.
Add RebootRequired and NoAutoRebootWithLoggedOnUsers info.
Add optional list of pending updates. This takes 30+ seconds, so allow
suppressing by setting new $ShowPendingUpdates param to $false or 0.
04/08/2015 - When listing updates, include optional updates (remove "BrowseOnly=0" criterion).
Add BrowseOnly and IsDownloaded columns to update list.
Note that Windows Defender updates include bundled updates for the base engine etc.
so total size will be 400MB+. Most of the "sub-updates" show IsInstalled=True but
are still included in total size. Getting true size would require looping through
bundled updates, which I won't try to do now.
04/17/2015 - Edit note about optional updates. Add note about Microsoft anti-virus update size.
11/12/2015 - Also list hidden updates if ShowPendingUpdates = $true.
02/17/2016 - Change default for $ShowPendingUpdates to $false. This lets script execute quickly
when run with no params.
- For Windows 8/8.1/2012/2012R2, show start trigger of the Regular Maintenance task,
which controls when updates are installed. No longer used in Windows 10.
08/04/2016 - When displaying pending updates, use Format-Table -AutoSize to show entire Title.
Add a column for UpdateID with RevisionNumber.
Output may now be up to 200 characters wide--you may want to copy to a text
editor without line wrapping.
08/04/2016 - If the machine is configured to get updates from WSUS, identify the WUServer and
WUStatusServer. Otherwise indicated that WSUS is not configured.
#>
param(
[Parameter(Mandatory = $false,
Position = 0,
ValueFromPipelineByPropertyName = $true)]
[Boolean]$ShowPendingUpdates=$false,
[Parameter(Mandatory = $false,
Position = 1,
ValueFromPipelineByPropertyName = $true)]
[String]$LogFile=""
)
[Boolean]$ErrFound = $false
"Computer Name: " + $env:COMPUTERNAME
""
"Microsoft AutoUpdate settings"
# The output below starts with two line breaks, so omit the newline here
Write-Host -NoNewLine ("-----------------------------")
try {
$objAutoUpdateSettings = (New-Object -ComObject "Microsoft.Update.AutoUpdate").Settings
$objSysInfo = New-Object -ComObject "Microsoft.Update.SystemInfo"
$objAutoUpdateSettings
"Reboot required : " + $objSysInfo.RebootRequired
# NoAutoReboot can apparently only be set by policy, so report that here.
# Reference: https://technet.microsoft.com/en-us/library/cc720464%28v=ws.10%29.aspx.
Write-Host -NoNewLine ("NoAutoRebootWithLoggedOnUsers : ")
try {
# If Get-ItemProperty fails, value is not in registry. Do not fail entire script.
# "-ErrorAction Stop" forces it to catch even a non-terminating error.
$output = Get-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate\AU -Name NoAutoRebootWithLoggedOnUsers -ErrorAction Stop
switch ($output.NoAutoRebootWithLoggedOnUsers)
{
0 {"False (set in registry)"}
1 {"True (set in registry)"}
}
}
catch {
"Unknown (local policy registry value not found)"
}
# WSUS server info, if available
# Reference: https://technet.microsoft.com/en-us/library/dd939844(v=ws.10).aspx
""
Write-Host -NoNewLine ("WSUS Server : ")
try {
# If Get-ItemProperty fails, value is not in registry. Do not fail entire script.
# "-ErrorAction Stop" forces it to catch even a non-terminating error.
$output = Get-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate -Name WUServer -ErrorAction Stop
$output.WUServer
}
catch {
"WSUS not configured. The machine must be contacting Windows Update directly."
}
Write-Host -NoNewLine ("WSUS Status Server : ")
try {
$output = Get-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate -Name WUStatusServer -ErrorAction Stop
$output.WUStatusServer
}
catch {
"WSUS not configured. The machine must be contacting Windows Update directly."
}
# Static info on the meaning of various Settings.
""
"NotificationLevel:"
"1 - Never check for updates"
"2 - Check for updates but let me choose whether to download and install them"
"3 - Download updates but let me choose whether to install them"
"4 - Install updates automatically"
""
"ScheduledInstallationDay:"
"0 - Every day"
"1-7 - Sunday through Saturday"
"Note: On Windows 8/8.1/2012/2012R2, ScheduledInstallationDay and"
" ScheduledInstallationTime are only reliable if the values"
" are set through Group Policy."
""
# For Windows 8/8.1/2012/2012R2, show start trigger of the Regular Maintenance task
# Per http://stackoverflow.com/a/26003354/550712 .NET OS Version is inaccurate on an
# upgraded Windows 8.1 machine, so use Get-CimInstance if available, else fall back to .NET.
# Cast as [Version] to allow accurate comparisons even when Version.Major is two digits (Windows 10).
[Version]$OSVersion = $null
try {
$OSVersion = (Get-CimInstance Win32_OperatingSystem).Version
}
catch {
# Get-CimInstance requires PowerShell 3. Fall back to .NET if Get-CimInstance doesn't work.
$OSVersion = [System.Environment]::OSVersion.Version
}
# List of Windows versions: http://www.robvanderwoude.com/ver.php
if ( ($OSVersion -ge [Version]"6.2.9200") -and ($OSVersion -le [Version]"6.3.9600") ) {
"Windows 8 / 8.1 / 2012 / 2012R2 scheduled maintenance"
"-----------------------------------------------------"
try {
"""\Microsoft\Windows\TaskScheduler\Regular Maintenance"" task trigger:"
$task = Get-ScheduledTask –TaskName "Regular Maintenance" -TaskPath "\Microsoft\Windows\TaskScheduler\" -ErrorAction Stop
$task.Triggers
}
catch {
"Error: Could not retrieve \Microsoft\Windows\TaskScheduler\Regular Maintenance task"
""
}
# To change, use
# $TaskTime = New-ScheduledTaskTrigger -At 12:00 -Daily
# Set-ScheduledTask –TaskName "Regular Maintenance" -TaskPath "\Microsoft\Windows\TaskScheduler\" –Trigger $TaskTime -ErrorAction Stop
}
"Pending Software Updates including Hidden Updates"
"-------------------------------------------------"
if ($ShowPendingUpdates) {
#Get All Assigned updates in $SearchResult.
$UpdateSession = New-Object -ComObject Microsoft.Update.Session
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
# Available search criteria: https://msdn.microsoft.com/en-us/library/windows/desktop/aa386526%28v=vs.85%29.aspx
# "BrowseOnly=0" omits updates that are considered "Optional" (e.g. Silverlight, hardware drivers).
# As of 4/8/2015, omit "BrowseOnly=0" so we'll see all available updates.
# Include "IsAssigned=1" to only see updates intended for deployment by Automatic Updates:
# $SearchResult = $UpdateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0")
# Omit "IsAssigned=1" to also see Recommended updates:
$SearchResult = $UpdateSearcher.Search("IsInstalled=0")
#Extract Results for type of updates that are needed. For to be arrays so we can .count them.
[Object[]] $Critical = $SearchResult.updates | where { $_.MsrcSeverity -eq "Critical" }
[Object[]] $Important = $SearchResult.updates | where { $_.MsrcSeverity -eq "Important" }
[Object[]] $Moderate = $SearchResult.updates | where { $_.MsrcSeverity -eq "Moderate" }
[Object[]] $Low = $SearchResult.updates | where { $_.MsrcSeverity -eq "Low" }
[Object[]] $Unspecified = $SearchResult.updates | where { $_.MsrcSeverity -eq "Unspecified" }
[Object[]] $Other = $SearchResult.updates | where { $_.MsrcSeverity -eq $null }
#Write Results
"Critical : $($Critical.count)"
"Important : $($Important.count)"
"Moderate : $($Moderate.count)"
"Low : $($Low.count)"
"Unspecified : $($Unspecified.count)"
"Other : $($Other.count)"
"Total : $($SearchResult.updates.count)"
""
"Notes: ""BrowseOnly"" updates are considered optional."
" Microsoft anti-virus updates include sub-updates"
" that are already installed, so size is inaccurate."
# "If" statement in Expression:
# http://blogs.technet.com/b/josebda/archive/2014/04/19/powershell-tips-for-building-objects-with-custom-properties-and-special-formatting.aspx
# Formatting number as MB: https://technet.microsoft.com/en-us/library/ff730948.aspx
# Available update properties (IUpdate interface): https://msdn.microsoft.com/en-us/library/windows/desktop/aa386099(v=vs.85).aspx
# Use Out-String to keep AutoSize from truncating columns based on screen size:
# https://poshoholic.com/2010/11/11/powershell-quick-tip-creating-wide-tables-with-powershell/
""
"Ready to Install"
"----------------"
$NotHiddenUpdates = $SearchResult.updates | Where-Object {$_.IsHidden -eq $false}
If ($NotHiddenUpdates -eq $null) {
"None"
} else {
$NotHiddenUpdates | Sort-Object MsrcSeverity, Title | `
Format-Table -AutoSize @{Expression={if ($_.MsrcSeverity -eq $null) {"Other"} else {$_.MsrcSeverity} };Label="Severity"}, `
@{Expression={$_.Title};Label="Title"}, `
@{Expression={"{" + $_.Identity.UpdateID + "}." + $_.Identity.RevisionNumber};Label="UpdateID and RevisionNumber"}, `
@{Expression={$_.BrowseOnly};Label="BrowseOnly"}, `
@{Expression={$_.IsDownloaded};Label="IsDownloaded"}, `
@{Expression={"{0:N1} MB" -f ($_.MaxDownloadSize / 1MB) };Label="MaxDownload";align="right"} | `
Out-String -Width 200
}
""
"Hidden Updates"
"--------------"
$HiddenUpdates = $SearchResult.updates | Where-Object {$_.IsHidden -eq $true}
If ($HiddenUpdates -eq $null) {
"None"
} else {
$HiddenUpdates | Sort-Object MsrcSeverity, Title | `
Format-Table -AutoSize @{Expression={if ($_.MsrcSeverity -eq $null) {"Other"} else {$_.MsrcSeverity} };Label="Severity"}, `
@{Expression={$_.Title};Label="Title"}, `
@{Expression={"{" + $_.Identity.UpdateID + "}." + $_.Identity.RevisionNumber};Label="UpdateID and RevisionNumber"}, `
@{Expression={$_.BrowseOnly};Label="BrowseOnly"}, `
@{Expression={$_.IsDownloaded};Label="IsDownloaded"}, `
@{Expression={"{0:N1} MB" -f ($_.MaxDownloadSize / 1MB) };Label="MaxDownload";align="right"} | `
Out-String -Width 200
}
} else {
"The ShowPendingUpdates parameter is False, so pending updates not listed."
""
} # if $ShowPendingUpdates
"Script execution succeeded"
$ExitCode = 0
} # try
catch {
""
$error[0]
""
"Script execution failed"
$ExitCode = 1001 # Cause script to report failure in MaxFocus RM dashboard
}
""
"Local Machine Time: " + (Get-Date -Format G)
"Exit Code: " + $ExitCode
Exit $ExitCode