Fragensteller
Solution! Implement Windows Update in OSD Task Sequence.

Allgemeine Diskussion
-
Hi,
while searching for an solution to deploy a complete installed and configured Windows 7 OS with SCCM i have build the following solution to
integrate the Windows Update process in an OSD task sequence.The advantage of this procedure is that the whole progress of the deployment will be shown in the original SCCM progress UI, and that you have an integrated, automated workflow installing the machine in an actual OS-state.
Here are the Steps to build the SCCM Package.
Step 1. In the new installed Windows PC you must install the correct Windows Update Agent for your OS Version.
For Example, on my Windows 7 Machines I actually need version 7.4.7600.226 (WindowsUpdateAgent30-x86.exe) to work with WSUS.
Step 2. The following scripts and files are also needed, they actually provide the automated WSUS patch installation integration.
- PSEXEC.EXE (Microsoft / Sysinternals)
- AU.REG
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate] "WUServer"="http://wsus.company.com:8530" "WUStatusServer"="http://wsus.company.com:8530" [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU] "AUPowerManagement"=dword:00000001 "NoAutoUpdate"=dword:00000000 "AUOptions"=dword:00000004 "ScheduledInstallDay"=dword:00000000 "ScheduledInstallTime"=dword:00000003 "UseWUServer"=dword:00000001 "NoAutoRebootWithLoggedOnUsers"=dword:00000001 "RebootRelaunchTimeoutEnabled"=dword:00000001 "RebootRelaunchTimeout"=dword:0000003c [HKEY_CURRENT_USER\Software\Sysinternals] [HKEY_CURRENT_USER\Software\Sysinternals\PsExec] "EulaAccepted"=dword:00000001
- UPDATE.CMD
@echo off regedit /s %~dp0au.reg copy %~dp0update.vbs %temp%\update.vbs %~dp0psexec.exe -i 1 -s wscript.exe %temp%\update.vbs del %temp%\update.vbs
- UPDATE.VBS
'========================================================================== ' ' NAME: SCCM Windows Update Task Sequence ' ' AUTHOR: Lutz Fiebach , NEXT GHmbH ' DATE : 23.07.2010 ' '========================================================================== On error Resume Next Class DummyClass Public Default Function DummyFunction() End Function End Class Dim gObjShell, gObjProgressUI, gObjFileSystem, strScriptPath, strCommand, strCurrentUpdate Dim gObjSearchResult, gObjUpdateSearcher, gObjUpdateSession, gObjUpdateCollection, gStrTmpDir Dim gStrWinDir, objDownload, objInstall, gObjDummyDict, varScriptPath, gStrOrgName, gStrTSName Set gObjShell = CreateObject("WScript.Shell") Set gObjFileSystem = CreateObject("Scripting.FileSystemObject") Set gObjUpdateSession = CreateObject("Microsoft.Update.Session") Set gObjUpdateCollection = CreateObject("Microsoft.Update.UpdateColl") Set gObjProgressUI = CreateObject("Microsoft.SMS.TsProgressUI") Set gObjDummyDict = CreateObject("Scripting.Dictionary") Call gObjDummyDict.Add("DummyFunction", New DummyClass) gStrOrgName = "COMPANY" gStrTSName = "Microsoft Windows Update" gStrWinDir = gObjShell.ExpandEnvironmentStrings("%windir%") gStrTmpDir = gObjShell.ExpandEnvironmentStrings("%temp%") Set gObjUpdateDownloader = gObjUpdateSession.CreateUpdateDownloader() fncDebugLog "update.vbs::main", "CreateUpdateDownloader" & vbTab & "Result: " & err.description & "(" & err.number & ")" Set gObjUpdateInstaller = gObjUpdateSession.CreateUpdateInstaller() fncDebugLog "update.vbs::main", "CreateUpdateInstaller" & vbTab & "Result: " & err.description & "(" & err.number & ")" varScriptPath = split(WScript.ScriptFullName, "\") For x = 0 To ubound(varScriptPath) - 1 strScriptPath = strScriptPath & varScriptPath(x) & "\" Next fncDebugLog "update.vbs::main", "strScriptPath :" & strScriptPath & vbTab & "Result: " & err.description & "(" & err.number & ")" strCommand = gStrWinDir & "\System32\CCM\TsProgressUI.exe /Register" gObjShell.Run strCommand,0 ,1 fncDebugLog "update.vbs::main", "Run :" & strCommand & vbTab & "Result: " & err.description & "(" & err.number & ")" '## Call gObjProgressUI.ShowActionProgress(gStrOrgName, gStrTSName, gStrTSName, _ "Windows Update initialize ...", 1, 4, _ "Configure Windows Update ...", 3, 4) '## Call gObjProgressUI.ShowActionProgress(gStrOrgName, gStrTSName, gStrTSName, _ "Windows Update initialize ...", 1, 4, _ "Stopping Service ...", 3, 4) strCommand = "net stop wuauserv" gObjShell.Run strCommand,0 ,1 fncDebugLog "update.vbs::main", "Run :" & strCommand & vbTab & "Result: " & err.description & "(" & err.number & ")" '## Call gObjProgressUI.ShowActionProgress(gStrOrgName, gStrTSName, gStrTSName, _ "Windows Update initialize ...", 1, 4, _ "Starting Service ...", 4, 4) strCommand = "net start wuauserv" gObjShell.Run strCommand,0 ,1 fncDebugLog "update.vbs::main", "Run :" & strCommand & vbTab & "Result: " & err.description & "(" & err.number & ")" '## WScript.Sleep 500 Call gObjProgressUI.ShowActionProgress(gStrOrgName, gStrTSName, gStrTSName, _ "Windows Update search ...", 2, 4, _ "Checking for Updates ...", 0, 1) '## Set gObjUpdateSearcher = gObjUpdateSession.CreateupdateSearcher() fncDebugLog "update.vbs::main", "CreateupdateSearcher" & vbTab & "Result: " & err.description & "(" & err.number & ")" Set gObjSearchResult = gObjUpdateSearcher.Search("IsInstalled=0 and Type='Software'") fncDebugLog "update.vbs::main", "Search(IsInstalled=0 and Type=Software)" & vbTab & "Result: " & err.description & "(" & err.number & ")" fncDebugLog "update.vbs::main", "UpdateCount :" & gObjSearchResult.Updates.Count & vbTab & "Result: " & err.description & "(" & err.number & ")" Call gObjProgressUI.ShowActionProgress(gStrOrgName, gStrTSName, gStrTSName, _ "Windows Update search ...", 3, 4, _ "Checking for Updates ...", 1, 1) WScript.Sleep 500 If gObjSearchResult.Updates.Count < 1 Then fncDebugLog "update.vbs::main", "Abort : No Updates Found!" & vbTab & "Result: " & err.description & "(" & err.number & ")" Call gObjProgressUI.ShowActionProgress(gStrOrgName, gStrTSName, gStrTSName, _ "Windows Update finalize ...", 4, 4, _ "No Updates available !", 1, 1) WScript.Sleep 1000 Set gObjProgressUI = Nothing WScript.Quit Else gObjUpdateDownloader.Updates = gObjSearchResult.Updates gObjUpdateInstaller.Updates = gObjSearchResult.Updates Set objDownload = gObjUpdateDownloader.BeginDownload(gObjDummyDict.Item("DummyFunction"), _ gObjDummyDict.Item("DummyFunction"), _ vbNull) fncDebugLog "update.vbs::main", "BeginDownload" & vbTab & "Result: " & err.description & "(" & err.number & ")" '## Download Updates While Not objDownload.IsCompleted = True If strCurrentUpdate <> gObjUpdateDownloader.Updates.Item(objDownload.GetProgress.CurrentUpdateIndex).Title Then strCurrentUpdate = gObjUpdateDownloader.Updates.Item(objDownload.GetProgress.CurrentUpdateIndex).Title fncDebugLog "update.vbs::main", "Download :" & strCurrentUpdate & vbTab & "Result: " & err.description & "(" & err.number & ")" End If Call gObjProgressUI.ShowActionProgress(gStrOrgName, _ gStrTSName, _ "", _ "Windows Update download (" & (objDownload.GetProgress.CurrentUpdateIndex + 1) & " / " & objDownload.Updates.Count & ")", _ objDownload.GetProgress.CurrentUpdateIndex, _ objDownload.Updates.Count - 1, _ gObjUpdateDownloader.Updates.Item(objDownload.GetProgress.CurrentUpdateIndex).Title, _ objDownload.GetProgress.CurrentUpdatePercentComplete , _ 100) WScript.Sleep 100 Wend Set objDownload = Nothing '## Install Updates Set objInstall = gObjUpdateInstaller.BeginInstall(gObjDummyDict.Item("DummyFunction"), _ gObjDummyDict.Item("DummyFunction"), _ vbNull) fncDebugLog "update.vbs::main", "BeginInstall" & vbTab & "Result: " & err.description & "(" & err.number & ")" While Not objInstall.IsCompleted = True If strCurrentUpdate <> gObjUpdateInstaller.Updates.Item(objInstall.GetProgress.CurrentUpdateIndex).Title Then strCurrentUpdate = gObjUpdateInstaller.Updates.Item(objInstall.GetProgress.CurrentUpdateIndex).Title fncDebugLog "update.vbs::main", "Install :" & strCurrentUpdate & vbTab & "Result: " & err.description & "(" & err.number & ")" End If Call gObjProgressUI.ShowActionProgress(gStrOrgName, _ gStrTSName, _ "", _ "Windows Update install (" & (objInstall.GetProgress.CurrentUpdateIndex + 1) & " / " & objInstall.Updates.Count & ")", _ objInstall.GetProgress.CurrentUpdateIndex, _ objInstall.Updates.Count - 1, _ gObjUpdateInstaller.Updates.Item(objInstall.GetProgress.CurrentUpdateIndex).Title, _ objInstall.GetProgress.CurrentUpdatePercentComplete , _ 100) WScript.Sleep 250 Wend Set objInstall = Nothing End If Function fncDebugLog(strFunction, strMessage) Dim objLogFile Set objLogFile = gObjFileSystem.OpenTextFile(gStrTmpDir & "\sccm_wsus_ts.log", 8, 1) objLogFile.WriteLine now() & vbTab & strFunction & vbTab & strMessage objLogFile.Close Set objLogFile = Nothing End Function
At this stage you will have an package directory with 5 files:
1. PSEXEC.EXE
2. update.cmd
3. update.vbs
4. AU.REG
5. WindowsUpdateAgent30-x86.exeStep 3. Create an SCCM package named "PKG_Windows_Update" and set the directory containig your files as source.
Step 4. Create an Programm in this Package named "Install Update Agent" to Install the Update Agent.
(example: WindowsUpdateAgent30-x86.exe /norestart /quiet)Step 5. Create an Programm namend "Install Updates" that starts the update.cmd.
Step 6. Add the "Install Update Agent" Programm one step before the "Install Updates" Programm to your OSD Task Sequence.
Description of the Process:
The "update.cmd" file imports the Windows Update Configuration and Starts the UPDATE.VBS with PSEXEC.EXE.
PSEXEC.EXE is needed to start the Script in the environment session of the SCCM Progress UI.Then the script creates an "Windows Update Session", "Update Searcher", "Update Downloader" and "Update Installer" Object from the Windows Update API.
First the update searcher object returns an update collection of all available updates.
After finishing the update search the collection is assigned to the update downloader object, and an asynchronus download starts.During the download progress a loop will monitor the current progress an put it into the SCCM ProgressUI.
When the download has finished the collection is assigned to the update installer object and an asynchronus install starts.
Now another loop monitors the installation and puts it into the UI.
Conclusion:
This is the Solution to integrate all actually provided Updates to your SCCM OSD Task Sequence.
One Step to build an Zero Touch Oparating System Deployment in your Environment.
Alle Antworten
-
Hey lufi99, just wanted to say thanks, I have been writing a HTA in VBScript do manipulate windows update, your code helped me to work out how to use the gObjUpdateDownloader.BeginDownload interface.
Thanks very much, I have credited you in my app.
-
Lufi this is excellent - I've tested in my SCCM Win 7x64 deployment and it works very well building a couple of VMs. I'll try it out on some more physical machines. This sort of information is so vital - I can't tell you how much this has helped our environment. Brilliant. I hope you visit this page and I hope your work doesn't go unoticed.
Thanks,
Stephen
-
Lufi this is excellent - I've tested in my SCCM Win 7x64 deployment and it works very well building a couple of VMs. I'll try it out on some more physical machines. This sort of information is so vital - I can't tell you how much this has helped our environment. Brilliant. I hope you visit this page and I hope your work doesn't go unoticed.
Thanks,
Stephen
Did you have to change anything in the script? I really need something like this to work for us. when i added it to my TS you can see it in the progress bar doing something. but when i check the client it has the updates downloaded but i have to click to force the install. -
Guys,
I have been working for a couple of days trying to get this script work. ;-) If I run it as suggested on this site the download updates portion works great, however when the install routine takes over it loops with an error stating: Install Update X, Result: Object Required(424). (As seen in the sccm_wsus_ts.log)
If I press F8 and open a cmd console and run the script manually it seems to work great, but when running from the task in the TS it always loops in the error above.
Still troubleshooting but hoping maybe someone can point me in the right direction if you have any ideas ;-)
Thanks!
-
To add a bit more to this, looking closer at the log it appears the error may start at:
Set objInstall = gObjUpdateInstaller.BeginInstall(gObjDummyDict.Item("DummyFunction"), _
gObjDummyDict.Item("DummyFunction"), _
vbNull)The following error shows in the log: BeginInstall Result: (-2145124330)
Thanks!
-
Wanted to follow up. It seems that the error comes when trying to initiate the install via the script. Once I traced back the error it showed that it couldnt create the object because an install was already underway. So after the patches download the install happens automatically so I added logic in the script (a variation of your script) to loop until the object creation equals 0, which in effect means once all the patches are done installing.
Not sure why this happens though. Maybe its a windows update registry configuration issue? I'll keep poking at it but with the added loop I am successfuly getting all pacthes installed during my TS.
-
More to add. :-) It appears that if I let GPO apply the Windows Update settings as normal it causes the updates to install and the script to tell me they are already installing. I paused the process, deleted all but the WUServer/WUStatusServer and the UseWUServer entries and the script is no longer throwing the error. :-)
As you can tell we dont use a staging OU. Positive I can work around this to get everything working as expected now. Thanks!
-
-
Hi,
I've been running a similar script for quite some time but ran into problems with it around the time Win7 SP1 was released.
I've now swapped over to use this script so I can see what is happening during the task sequence and because the logging feature is helping me debug the problems I've found.
I also ran into the Install Update X, Result: Object Required(424) issue. It was due to the script not adding the registry setting AcceptTrustedPublisherCerts. It meant that the script would detect the Adobe Flash/Reader updates we have published to our WSUS server via SCUP as available for install but fail to download them because it's disabled in registry by default. When the script comes to install it the file isn't there... Hence 'object required'. Setting that registry value to 1 got it working. It also does it if the certificates used on the server to sign the updates aren't installed in the task sequence using the certutil.exe program.
It aslo did the same for a Windows Defender update. Just unappproved all the Windows Defender updates, did a server clean up, re-approved them then did a server sync. This cured the problem, Think the update must have corrupted in WSUS or something.
-
and another quick update:
I've just run into the BeginInstall Result: (-2145124330) eror that you've also had. For me it was due to me installing Forefront Endpoint Protection 2010 as part of my task sequence. That kicks off an automatic update after it has installed. By the time my script had downloaded it's available updates, Forefront was already busy updating it's virus definitions so I'd get the (-2145124330) error in the logs.
I just added a couple of lines to run a "net stop MsMpSvc" and it prevents forefront from beating the script to the install.
-
...and finally, I never maneaged to get it working. On XP machines the task sequence engine runs in session 0 rather than session 1. I altered the psexec command line to reflect this but the feedback is not shown.
I then tried the serviceui.exe tool that comest with MDT2010 Rollup 1. Same results. As XP's days are limited in my environment I decided not to dedicate any more time to it.
If anyone does actually read my self-ramblings here who has got it to work, please reply to let me know...
-
Hi there, when trying your script, I get the following errors.
Any suggestions?
Straight from the sccm_wsus_ts log file
2/21/2012 6:55:34 PM update.vbs::main CreateUpdateDownloader Result: ActiveX component can't create object(429)
2/21/2012 6:55:34 PM update.vbs::main CreateUpdateInstaller Result: ActiveX component can't create object(429)
2/21/2012 6:55:34 PM update.vbs::main strScriptPath :C:\Users\ADMINI~2\AppData\Local\Temp\ Result: ActiveX component can't create object(429)
2/21/2012 6:55:34 PM update.vbs::main Run :C:\Windows\System32\CCM\TsProgressUI.exe /Register Result: (-2147024894)
2/21/2012 6:55:36 PM update.vbs::main Run :net stop wuauserv Result: Object required(424)
2/21/2012 6:55:38 PM update.vbs::main Run :net start wuauserv Result: Object required(424)
2/21/2012 6:55:39 PM update.vbs::main CreateupdateSearcher Result: Object required(424)
2/21/2012 6:55:43 PM update.vbs::main Search(IsInstalled=0 and Type=Software) Result: (-2147012867)
2/21/2012 6:55:43 PM update.vbs::main Abort : No Updates Found! Result: Object required(424)This occurs running from my task sequences or from running it manually.
Thanks!
Wes
-
I added this to update.cmd to get round that issue (I set all my registry stuff in update.cmd):
REG ADD HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v AcceptTrustedPublisherCerts /t REG_DWORD /d 1 /f
Mine was due to having SCUP updates in our WSUS database though. It seems your script is failing prior to that so I'm not sure if this will help.
You're definitely running Windows Update agent 7.4.7600.226?
-
This script works on some machines and others not. we use HP 84XX, 25XX and 85XX and on those it works but im not getting any status in TS on how the updates are going. on our desktop modells it works great i get status in TS, in my "Capture reference image task sequence" wich i run on VMWare it just stops on the install updates step. if i check the SMS TS log it sais waiting for status notification.
ive tried a staging OU, i even have 1 script that deletes all the windows update registry keys so that im sure that the keys that are applied are the right ones.
My best guess is that its driver related, but ive tried atleast 5 different NIC drivers and its still the same.
If i however run a task sequence when windows is deployed and only use the steps to install updates it works on every modell...
-
On my VM this was due to the download that got stuck on 1%.
I got the status working on all my modells by deleting the last 2 lines of the update.cmd that runs the actuall update, i then added a run command line and just ran the update.vbs there instead, it states that you need to run PsExec to get the status to the TSProgress but in my case it works without it. i Also added these lines in the update.cmd just to get a clean softwaredistribution folder, ive had alot of issues with this in the past and shuting down the windows update service and then deleting everything in the softwaredistribution folder has been the solution in most cases. i added it just below @echo off
The regsvr is just something i added becouse i kept getting sync of updates error 0x8024400a
net stop wuauserv
@For /D %%I in (%windir%\SoftwareDistribution\*.*) DO RD /s /q %%I
regsvr32 /s wuapi.dll
regsvr32 /s wups.dll
regsvr32 /s wuaueng.dll
regsvr32 /s wuaueng1.dll
regsvr32 /s wucltui.dll
regsvr32 /s wuweb.dll
regsvr32 /s jscript.dll
regsvr32 /s atl.dll
regsvr32 /s softpub.dll
regsvr32 /s msxml3.dll
net start wuauserv