Windows Update Script Automation
Windows Update Script Automation
com"
'~~[author]~~
'Rob Dunn
'with some additional improvements made by the WSUS and Spiceworks community
' - thank you!
'~~[/author]~~
'
'~~[ContactInfo]~~
'https://community.spiceworks.com/people/robdunn
'~~[/ContactInfo]~~
'
'~~[website]~~
'For future versions and support:
'https://community.spiceworks.com/scripts/show/82
'~~[/website]~~
'
'~~[scriptType]~~
'vbscript
'~~[/scriptType]~~
'~~[subType]~~
'SystemAdministration
'~~[/subType]~~
'~~[keywords]~~
'wsus, windows, updates, hotfixes, email, windowsupdate, microsoft, wua, sus,
'~~[/keywords]~~
'
'~~[usage]~~
'****Install updates silently, email you a logfile, then restart the computer****
'updatehf.vbs action:install mode:silent email:you@yourdomain.com restart:1
'
'****Install KB4012213 silently, email you a logfile, then restart the computer****
'
'****Detect missing updates or pending reboot silently, email you a logfile, then
' restart if there is a pending reboot****
'updatehf.vbs action:detect mode:silent email:you@yourdomain.com restart:1
'
'****Detect missing updates or pending reboot silently, email you a logfile, then
' restart no matter if there is a pending reboot****
'updatehf.vbs action:detect mode:silent email:you@yourdomain.com restart:1 force:1
'
'~~[/usage]~~
'This script (the core was pulled from Microsoft's website - thank
' you!) will tell the WU agent to 'detectnow', download and install
' missing windows updates as compared to it's update server. Works for
' WSUS and regular Windows Update site.
'
'This will now reboot the computer if specified after the udpates have
' been applied (or if there is a reboot pending from a previous update session).
'
'NOTE: If there are a LOT of downloads to pull, the status window (or log)
' will say "Downloading" for that entire time. I'm not sure how to get
' a download progress of each update...maybe someone can help me with that.
'
'Note on command-line switches: If you don't specify a switch (for
' example, 'email:') the corresponding variable defined in the script will
' provide the needed information (command-line switches take precedence).
'
'Why I put this script together:
'Our desktop deployment technicians needed a script that would pull
' updates immediately and install, even if the update configuration is set
' for 'download only' via Group Policy.
'
'We have some computers that are sometimes logged on or not (but
' they run services that must be running almost constantly), and are never
rebooted.
'
'The user ignores the 'you have new updates available' message, so updates are
' never installed. This script will let you install the updates, and then it
' tells the WUA to present the 'restart' message - which more users are apt to
' respond to.
'
'After the script runs, it will email a recipient the resulting logfile that is
' produced.
'
'*******************************************************************************
'You need to edit the following variables:
'
'strMailFrom - arbitrary reply-to address
'strMailto - email address you want the report to mail to (this is for manual
' mode
' - or if the command-line switch isn't specified).
'strSMTPServer - the IP address of the email server you are sending the reports
' through.
'
'*******************************************************************************
'Optional variables:
'Silent - 0 = verbose, 1 = silent (no windows or visible information)
'Intdebug - 0 = off, 1 = 1 (see some variables that are being passed)
'strAction - prompt|install|detect. Prompt gives users opportunity to install
' updates or not, install just installs them, detect updates the WU collection
' and downloads the updates (but does not install them) - useful if you want to
' have the computer refresh its stats to the stat server but not install the
' updates.
'blnEmail - 0 = off|1 = on. If set to 0, the script will not email a log file.
' If you specify an email address in the command-line, this will force the
' script to switch blnEmail to '1'.
'strRestart - 0 = Do nothing|1 = restart|2 = shutdown. Command-switch 'restart:'
' supercedes this variable.
'
'*******************************************************************************
'Command line switches:
'action: prompt|install|detect
'updateid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (look up the updateID using the
Microsoft Update Catalog)
'mode: silent|verbose
'email: you@yourdomain.com
'restart: 0 (do nothing)| 1 (restart) | 2 (shutdown)
'force: 0 (do not enforce restart action - this is optional, by default it is
' set to 0) | 1 (enforce restart action).
'SMTPServer: x.x.x.x or hostname; overrides strSMTPServer above.
'emailsubject: "this is a subject" Overrides default subject. Server name is
appended to this text. Use quotes if spaces exist.
'emailifallok: 0|1, where 0 = dont send email if server up to date and no
' reboot pending, and 1 = always send email
'fulldnsname: 0|1, where 0 = use server name only in subject, and 1 = use full
' dns name in email subject
'authtype: cdoAnonymous|cdoNTLM|cdoBasic - authentication type for SMTP (default
' is 'cdoAnonymous', no creds needed)
'authID: SMTP authentication ID
'authPassword: SMTP authentication password
'Finally, rename the file with .vbs
'*******************************************************************************
Dim objArgs,strArgs
Dim l
Set objArgs = Wscript.Arguments
'Handle UAC
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName _
, WScript.ScriptFullName & " /elevate" & " " & strArguments, "", "runas", 1
WScript.Quit
End If
strUser = WshSysEnv("username")
strDomain = WshSysEnv("userdomain")
'Get computer OU
strOU = "Computer OU: Not detected"
If InStr(ucase(WScript.FullName),"CSCRIPT.EXE") Then
blnCScript = TRUE
Else
blnCScript = FALSE
End If
blnCloseIE = true
'*******************************************************************************
' User variables
'*******************************************************************************
'Turn on debugging. This will show some of the variables that are being passed
' while the script executes.
Intdebug = 0
'How long between the time that the script is finished and the IE window stays
' on the screen. Set to '0' if you don't want the status window to close
' automatically.
intSleep = 2000
'The location of the logfile (this is the file that will be parsed
' and the contents will be sent via email.
logfile = WshSysEnv("TEMP") & "\" & "vbswsus-status.log"
'who are you mailing to? Input mode only. Command-line parameters take
' precedence
strMailto = "you@yourdomain.com"
'The computer name will follow this text when the script completes.
strSubject = "[WSUS Update Script] - WSUS Update log file from"
'default option for manual run of the script. Possible options are:
' prompt - (user is prompted to install)
' install - updates will download and install
' detect - updates will download but not install
strAction = "install"
'tells the script to prompt the user (if running in verbose mode) to input the
' email address of the recipient they wish to send the script log file to. The
' default value in the field is determined by the strMailto variable above.
'
'This only appears if no command-line arguments are given.
'0 = do not prompt the user to type in an email address
'1 = prompt user to type in email address to send the log to.
promptemail = 0
'Tells the computer what to do after script execution if the script detects that
' there is a pending reboot.
'
'Command-prompt supercedes this option.
'0 = do nothing
'1 = reboot
'2 = shutdown
strRestart = 0
'Try to force the script to work through any errors. Since some are recoverable
' this might be an option for troubleshooting. Default is 'true'
blnIgnoreError = true
'sets font for display status dialog and sent formatted logfile
strFontStyle = "arial"
'SMTP authentication ID
strAuthID = ""
'*******************************************************************************
'End of User variables
'*******************************************************************************
l.writeline "Executed by: " & strDomain & "\" & strUser
l.writeline "Command arguments: " & strArguments
l.writeline "------------------------------------------------------------------"
'Call WMI query to collect parameters for reboot action
Set OpSysSet = GetObject("winmgmts:{(Shutdown)}//" & strComputer &
"/root/cimv2").ExecQuery("select caption,OSArchitecture,ServicePackMajorVersion
from Win32_OperatingSystem"_
& " where Primary=true")
For each item in OpSysSet
strOS = item.caption
strOSArchitecture = item.OSArchitecture
strSP = item.ServicePackMajorVersion
Next
If blnEmail = 1 then
writelog("SMTP Authentication type specified: " & strAuthType)
If lcase(strAuthType) <> "cdoanonymous" Then
If strAuthType = "" Then
strAuthType = "cdoanonymous"
Else
writelog("SMTP Auth User ID: " & sAuthID)
End If
End If
End If
'Call checkupdateagent
If strForceaction = 1 Then
strForceText = " (enforce action)"
Else
strForceText = " (only if action is pending)"
End If
Call GetAUSchedule()
If regWSUSServer then
Else
regWSUSServer = "http://windowsupdate.microsoft.com/"
End If
strValueName = "TargetGroup"
oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,regTargetGroup
if regTargetGroup <> "" then
writelog("Target Group: " & regTargetGroup)
Else
writelog("Target Group: Not specified")
End If
fstyle = "calibri,tahoma,arial,verdana"
bgcolor1 = "aliceblue"
fformat = "<font face='" & fstyle & "'>"
writelog("Instantiating Searcher")
If strKBID <> "" Then
writelog("Searching for specific UpdateID: " & strKBID)
strQuery = "UpdateID='" & strKBID & "'"
Else
writelog("Checking for all approved updates according to WU agent")
strQuery = "IsAssigned=1 and IsHidden=0 and IsInstalled=0 and
Type='Software'"
End If
strMsg = "Error - [" & err.number & "] - " & chr(34) & errdescription & chr(34)
& "." & vbcrlf & vbcrlf _
& "This error is undefined in the script, but you can refer to " & strAddr & "
to look up the error number." _
& strScriptAbort
strMsgHTML = replace(strMsg,strAddr,"<a href='" & strAddr & "'>" & strAddr &
"</a>")
If silent = 0 Then objdiv.innerhtml = replace(strMsgHTML,"vbcrlf","<br>")
End If
Call ErrorHandler("UpdateSearcher",strMsg,blnFatal)
End If
'ssManagedServer
If silent = 0 then
writelog("Calling IE Status Window")
on error goto 0
Call IEStatus
End If
Call CheckPendingStatus("beginning")
strMsg = "WUA mode: <font color='navy'>" & strACtion & "</font><br>WU Server: " &
regWSUSServer _
& "<br>Target Group: " & regTargetGroup & "<br><br>List of applicable items on the
machine: <br>"
writelog("WUA mode: " & straction)
writelog("WU Server: " & regWSUSServer)
Else
writelog(regWSUSServer & "/iuident.cab Status: " & URLGet(regWSUSServer &
"/iuident.cab"))
End If
For i = 0 To searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(i)
'if update.MsrcSeverity = "Important" then wscript.echo "This item (" &
update.Title & ") is " & update.MsrcSeverity
strSearchResultUpdates = strSearchResultUpdates & update.Title & "<br>"
Set objCategories = searchResult.Updates.Item(i).Categories
writelog("Missing: " & searchResult.Updates.Item(i))
Next
blnFatal = false
End IF
If searchResult.Updates.Count = 0 Then
strMsg = fformat & "There are no further updates needed for your PC at this
time."
writelog(replace(strMsg,fformat,""))
writelog("Events saved to '" & logfile & "'")
Call EndOfScript
wscript.quit
End If
For I = 0 to searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(I)
if update.MsrcSeverity <> "" then MsrcSeverity = "(" & update.MsrcSeverity &
") "
strUpdates = strUpdates & MsrcSeverity & "- " & update.Title & "<br>"
writelog("Cataloged: " & MsrcSeverity & update.Title)
If Not update.EulaAccepted Then update.AcceptEula
updatesToDownload.Add(update)
Next
Else
strUpdates = ""
strMsg = ""
if silent = 0 then objdiv.innerhtml = ""
strMsg = fformat & "List of downloaded updates: <br><br>"
if silent = 0 then objdiv.innerhtml = strMsg
For I = 0 To searchResult.Updates.Count-1
Set update = searchResult.Updates.Item(I)
If update.IsDownloaded Then
strDownloadedUpdates = strDownloadedUpdates & update.Title & "<br>"
End If
On Error GoTo 0
'writelog(searchResult.Updates.Item(i))
writelog("Downloaded: " & update.Title)
if silent = 0 then objdiv.innerhtml = strMsg & strDownloadedUpdates
Next
strUpdates = ""
strMsg = ""
if silent = 0 then objdiv.innerhtml = ""
strMsg = fformat & "Creating collection of updates needed to
install:<br><br>"
For I = 0 To searchResult.Updates.Count-1
set update = searchResult.Updates.Item(I)
If update.IsDownloaded = true Then
strUpdates = strUpdates & update.Title & "<br>"
updatesToInstall.Add(update)
End If
writelog("Adding to collection: " & update.Title)
if silent = 0 then objdiv.innerhtml = strMsg & strUpdates
Next
End If
Call EndOfScript
wscript.quit
ElseIf strAction = "install" Then
strResult = 6
End If
strUpdates = ""
if silent = 0 then objdiv.innerhtml = ""
If strResult = 7 Then
strMsg = strMsg & "<br>User cancelled installation. This window can be closed."
writelog(replace(strMsg,"<br>",""))
WScript.Quit
ElseIf strResult = 6 Then
strMsg = ""
Set installer = updateSession.CreateUpdateInstaller()
installer.AllowSourcePrompts = False
on error resume next
installer.ForceQuiet = True
' If silent = 0 Then objdiv.innerhtml = strMsg & "<br>• " & update.title
installer.Updates = updatesToInstall
blnInstall = true
writelog(replace(replace(strMsg,fformat,""),"<br>",""))
For i = 0 to updatesToInstall.Count - 1
If installationResult.GetUpdateResult(i).ResultCode = 2 Then
strResult = "Installed"
ElseIf installationResult.GetUpdateResult(i).ResultCode = 1 Then
strResult = "In progress"
ElseIf installationResult.GetUpdateResult(i).ResultCode = 3 Then
strResult = "Error"
ElseIf installationResult.GetUpdateResult(i).ResultCode = 4 Then
strResult = "Failed"
ElseIf installationResult.GetUpdateResult(i).ResultCode = 5 Then
strResult = "Aborted"
End If
writelog(strResult & ": " & updatesToInstall.Item(i).Title)
strUpdates = strUpdates & strResult & ": " &
updatesToInstall.Item(i).Title & "<br>"
Next
if silent = 0 then objdiv.innerhtml = strMsg & strUpdates
End If
Call EndOfScript
wscript.quit
'*******************************************************************************
'Function Writelog
'*******************************************************************************
Function WriteLog(strMsg)
l.writeline "[" & time & "] - " & strMsg
' Output to screen if cscript.exe
If blnCScript Then WScript.Echo "[" & time & "] " & strMsg
End Function
'*******************************************************************************
'Function IE Status
'*******************************************************************************
Function IEStatus
If blnProgressMode Then
' in case people has used the search bar in IE, turn it off
' Thank you Torgeir!
Set IEtmp = CreateObject("InternetExplorer.Application")
IEtmp.ShowBrowserBar "{30D02401-6A81-11D0-8274-00C04FD5AE38}", False
IEtmp.Quit
Set IE = CreateObject("InternetExplorer.Application")
'strScriptVer = "version would go here"
ts.WriteLine("<script LANGUAGE='JavaScript1.2'>")
ts.WriteLine("<!-- Begin")
ts.WriteLine("function initArray() {")
ts.WriteLine("this.length = initArray.arguments.length;")
ts.WriteLine("for (var i = 0; i < this.length; i++) {")
ts.WriteLine("this[i] = initArray.arguments[i];")
ts.WriteLine(" }")
ts.WriteLine("}")
ts.WriteLine("var ctext = ' ';")
ts.WriteLine("var speed = 1000;")
ts.WriteLine("var x = 0;")
ts.WriteLine("var color = new initArray(")
ts.WriteLine("'red',")
ts.WriteLine("'blue'")
ts.WriteLine(");")
ts.WriteLine("document.write('<div id=" & Chr(34) & "ProgFlash" & Chr(34) &
">"_
& "<center>'+ctext+'</center></div>');")
ts.WriteLine("function chcolor(){")
ts.WriteLine("document.all.ProgFlash.style.color = color[x];")
ts.WriteLine("(x < color.length-1) ? x++ : x = 0;")
ts.WriteLine("}")
ts.WriteLine("setInterval('chcolor()',1000);")
ts.WriteLine("// End -->")
ts.WriteLine("</script>")
ts.WriteLine("<div id='ProgBarId' align='left'></div>")
ts.WriteLine("</font></center>")
ts.WriteLine("</tr></td>")
ts.WriteLine("</table></center>")
ts.WriteLine("</body></html>")
ts.Close
fctSetupIE(strTempFile)
Set objDIV = IE.Document.All("ProgObject")
If blnDebugMode Then
Set objDBG = IE.Document.All("ProgDebug")
End If
Set objFlash = IE.Document.All("ProgFlash")
Set objPBar = IE.Document.All("ProgBarId")
Set objBar = IE.Document
End If
If silent = 1 Then
'remarked by Rob Set logwindow = ie.document.all.text1
End If
End Function
'*******************************************************************************'*
Name: fctSetupIE
'* Function: Setup an IE windows of 540 x 200 to display
'* progress information.
'*******************************************************************************
Sub fctSetupIE(File2Load)
IE.Navigate File2Load
IE.ToolBar = dbgToolBar
IE.StatusBar = dbgStatusBar
IE.Resizable = dbgResizable
Do
Loop While IE.Busy
IE.Width = dbgWidth
IE.Height = dbgHeight
IE.Left = dbgLeft
IE.Top = dbgTop
IE.Visible = dbgVisible
wshshell.AppActivate("Microsoft Internet Explorer")
End Sub
Sub GetAUSchedule()
Set objAutoUpdate = CreateObject("Microsoft.Update.AutoUpdate")
Set objSettings = objAutoUpdate.Settings
If objSettings.ScheduledInstallationTime = 0 Then
strScheduledTime = "12:00 AM"
ElseIf objSettings.ScheduledInstallationTime = 12 Then
strScheduledTime = "12:00 PM"
Else
If objSettings.ScheduledInstallationTime > 12 Then
intScheduledTime = objSettings.ScheduledInstallationTime - 12
strScheduledTime = intScheduledTime & ":00 PM"
Else
strScheduledTime = objSettings.ScheduledInstallationTime & ":00 AM"
End If
'strTime = "Scheduled installation time: " & strScheduledTime
End If
writelog("Windows update agent is scheduled to run on " & strDay & " at " &
strScheduledTime)
End Sub
'*******************************************************************************
'Function URLGet - Check to see if web page is active
'
'Thanks to http://www.sebsworld.net/information/?page=VBScript-URL
'*******************************************************************************
Function URLGet(URL)
on error goto 0
' Set Http = CreateObject("WinHttp.WinHttpRequest.5.1")
' Set Http = CreateObject("WinHttp.WinHttpRequest.5")
' Set Http = CreateObject("WinHttp.WinHttpRequest")
' Set Http = CreateObject("Msxml2.ServerXMLHTTP.6.0")
' Set Http = CreateObject("MSXML2.ServerXMLHTTP")
Set Http = CreateObject("MSXML2.XMLHTTP")
' Set Http = CreateObject("Microsoft.XMLHTTP")
'msgbox URL
Http.Open "HEAD",URL,False
'const SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS = 13056
'Http.setOption 2, SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS
Http.Send
'pagestatus = Http.status
If Http.status <> "403" and Http.status <> "200" Then
URLGet = "(ERROR):" & Http.status
Else
'URLGet = Http.ResponseBody
'URLGet = Http.responseText
URLGet = "OK " & Http.status
End if
End Function
Function URLPost(URL,FormData,Boundary)
Set Http = CreateObject("Microsoft.XMLHTTP")
Http.Open "POST",URL,True
' Http.setRequestHeader "Content-Type","multipart/form-data; boundary="& Boundary
Http.send FormData
for n = 1 to 9
If Http.readyState = 4 then exit for
' Http.waitForResponse 1
b = shell.popup("Getting page",1,"Message")
next
If Http.readyState <> 4 then
URLPost = "Failed"
else
URLPost = Http.responseText
end if
End Function
'*******************************************************************************
'Function SendMail - email the warning file
'*******************************************************************************
Function SendMail(strFrom,strTo,strSubject,strMessage)
Dim iMsg, iConf, Flds
'If silent = 0 Then objdiv.innerhtml = "<font face=" & strFontStyle & " color=" &
strFontColor2& ">" _
' & "sending mail to " & strMailTo & "...</font><br>"
End if
'iMsg.AddAttachment wsuslog
iMsg.HTMLBody = replace(strMessage,vbnewline,"<br>")
'// Send the message.
on error resume next
End Function
'*******************************************************************************'Fu
nction RestartAction
'Sub to perform a restart action against the computer
'*******************************************************************************
Function RestartAction
If silent = 0 Then objdiv.innerhtml = strStatus & "<br> Now performing post-
execute action (" & restarttext & ")."
wscript.sleep 4000
writelog("Processing PostExecuteAction")
'On Error GoTo 0
Dim OpSysSet, OpSys
'writelog("Computer: " & strComputer & vbcrlf & "Post-execution action: " &
strRestart)
'On Error Resume Next
Const EWX_LOGOFF = 0
Const EWX_SHUTDOWN = 1
Const EWX_REBOOT = 2
Const EWX_FORCE = 4
Const EWX_POWEROFF = 8
'set PC to reboot
If strRestart = 1 Then
'set PC to shutdown
ElseIf strRestart = 2 Then
'Do nothing...
ElseIf strRestart = "0" Then
End If
End Function
'*******************************************************************************
'Sub ErrorHandler
'Sub to help display/log any errors that occur
'*******************************************************************************
Sub ErrorHandler(strSource,strMsg,blnFatal)
'Set theError = RemoteScript.Error
If silent = 0 then wscript.echo "Source: " & strSource & " - " & strMsg
writelog(strMsg)
If blnFatal = true then wscript.quit
err.clear
End Sub
'*******************************************************************************'Fu
nction EndOfScript
'Function to close out the script
'*******************************************************************************
Function EndOfScript
If blnEmail = 1 Then
If searchresult.updates.count = 0 and not blnRebootRequired and
StrEmailifAllOK = 0 then
writelog ("No updates required, no pending reboot, therefore not sending
email")
else
if strFullDNSName = 1 then
strDomainName = wshShell.ExpandEnvironmentStrings("%USERDNSDOMAIN%")
strOutputComputerName = strComputer & "." & StrDomainName
else
strOutputComputerName = strComputer
end if
if emailifallok = 0 or emailifallok = 1 then
if instr(strSMTPServer,"x") then
else
Call SendMail(strFrom,strTo,strSubject & " " &
strOutputComputerName,strMessage)
end if
end if
end if
Else
'l.close
End If
Exit Function
End Function
'*******************************************************************************
'Function CheckPendingStatus
'Function to restart the computer if there is a reboot pending...
'*******************************************************************************
Function CheckPendingStatus(beforeorafter)
Set ComputerStatus = CreateObject("Microsoft.Update.SystemInfo")
Select case beforeorafter
Case "beginning"
strCheck = "Pre-check"
Case "end"
strCheck = "Post-check"
Case Else
End Select
blnRebootRequired = ComputerStatus.RebootRequired
End Function
'*******************************************************************************