WSUS Offline as Postinstallation Task (XP & Win7) w/Progress Bar
Using WSUS Offline as a Postinstallation Task (XP & Win7)
I got this working with XP and Win7 scripted installs and thought this might be useful for others. Basically, you use WSUS Offline to download all specified updates and then setup a postinstallation task on the K2000 to install them during a scripted install. The ultimate result is time and bandwidth saved.
In short, I'm using two different approaches for setting up a WSUS Offline postinstallation task, so you can take your pick.
For my XP scripted installs, I used dchristian's suggestion to copy the updates from the K2000's petemp folder (\\k2000\petemp) as a midlevel task (K2000 Boot Environment - Windows), but the driver feed workaround for 3.3 broke this. This wasn't an issue for my XP installs as I'm loading the drivers as discrete postinstallation tasks (i.e. not using the driver feed workaround), but something to be aware of as you read through the steps. The 3.4 update with the driver feed fix built-in may not have this issue, but I'm still on 3.3 so can't confirm. Once thing nice about this approach is that when the midlevel task runs you get a command prompt screen that shows all of the files copying over. When running the update postinstallation task, I had the best results running this after a reboot (see my other post for setting up reboots during a scripted install if you need the steps). Basically, I load the drivers, Office, IE8, WMP11, reboot, buffer for reboot, sleep, WSUS update, reboot steps again, then load 3rd party apps, etc. I have the WSUS update program set to autoreboot, so only use the buffer for reboot and sleep tasks following this. Without the autoreboot, the WSUS update screen just sits there and I didn't want to waste time trying to find a way around this.
For my Win7 scripted installs, rather than host the update files on the K2000 (since the midlevel task gets broken by the driver feed workaround), I have them saved to a folder on our file server. Since copying the files over takes a while, I found a way to use a compiled AutoIT script to give a progress bar during the copy proccess. It also authenticates to the file server, copies the files, and kick off the update program which actually installs the files (last step the same as the update program in the XP method, if you compare the scripts). I also have the WSUS update program set to autoreboot and have this set as the last postinstallation task. At one point during testing I had this in the same place as in the XP scripted installs (and it worked fine), but aesthetically I like having it at the end as it makes troubleshooting the rest of the scripted install faster as I can cancel the WSUS update process, reboot the target machine and troubleshoot the earlier tasks. This can definitely help as the WSUS update process can take a bit to complete.
As for the steps to get this running, here's my notes. The AutoIT script for the "self-contained" Win7 postinstallation task follows.
________________________________________________________
XP Scripted Install - Setup & WSUS Offline Postinstallation Tasks
________________________________________________________
1) Download wsusoffline (link directly under Most Recent Version on right side of page)
* http://download.wsusoffline.net/
2) Create a folder on the PC which will be used to download files and extract files here
* i.e. c:\wsusoffline
3) Create wsusoffline folder under \\ikbox\petemp
4) Create client-targeted folders under \\ikbox\petemp\wsusoffline
* i.e. xpsp3-o2k3sp3-ie8-wmp11
* optional step, can keep all updates in one folder if desired and just reference wsusoffline folder for rest of steps
* however, doing it this way keeps the amount of files copied to clients minimized
* doing this would require multiple runs of WSUS Offline, each time targeting different OS, etc and different target folder
5) Run UpdateGenerator.exe and select desired Windows & Office updates and options
* ex: Windows XP, Office 2003
6) At the bottom under USB medium check "Copy updates for selected products into directory" and specify target
* ex: \\ikbox\petemp\wsusoffline\xpsp3-o2k3sp3-ie8-wmp11
7) Click Start button to initiate downloads
* this will take a while to complete
* when completed, should see folder structure under \\ikbox\petemp\wsusoffline with UpdateInstaller.exe
8) Run UpdateInstaller.exe on target PC and review selections, make note of desired changes, then close
* ex: Install Office File Converters, Install Office File Validation, Automatic reboot and recall
9) Edit UpdateInstaller.ini to includue/exclude changes (per previous step)
* ex: instofc=Enabled, instofv=Enabled, autoreboot=Enabled
10) K2000 - During scripted install, copy the client-targeted folder to client.
Create a new Postinstallation Task - BAT Script - K2000 Boot Environment (Windows)
Name: WSUS - Copy Files (XPSP3-O2K3SP3-IE8-WMP11)
BAT Script:
@echo off
echo WSUS Offline Updates to Local Machine
Xcopy T:\wsusoffline\xpsp3-o2k3sp3-ie8-wmp11 c:\kace /e /y /k
wpeutil reboot
* added wpeutil line because wasn't rebooting following copy
11) K2000 - During scripted install, run Update.exe file via AutoIT script (wsusupdate.exe).
Create a new Postinstallation Task - Application - Windows
Name: WSUS - Install Updates
Runtime Environment: Windows
Command Line: c:\kace\wsusupdate-xp.exe
* changed from calling update.cmd via a batch script due to premature reboot during scripted install
________________________________________________________
XP AutoIT Script
* referenced in step 11
* compile this as wsusupdate-xp.exe and save to update folder
* i.e. \\k2000\petemp\xpsp3-o2k3sp3-ie8-wmp11
________________________________________________________
Run("UpdateInstaller.exe")
WinWaitActive("WSUS Offline Update 7.3 - Installer")
ControlClick("WSUS Offline Update 7.3 - Installer", "Start", "Button24", "left", 1, 40, 12)
Sleep(100)
WinWaitActive("DoUpdate /nobackup /updatercerts /updatedx /updatewmp /updatetsc /instofc /instofv /verify /autoreboot")
;waits until no instance of cmd.exe exists
ProcessWaitClose("cmd.exe")
________________________________________________________
________________________________________________________
Win7 Scripted Install - Setup & WSUS Offline Postinstallation Task
________________________________________________________
1) Download wsusoffline (link directly under Most Recent Version on right side of page)
* http://download.wsusoffline.net/
2) Create a folder on the PC which will be used to download files and extract files here
* i.e. c:\wsusoffline
3) Create client-targeted folder under \\fileserver\kace\postinstalls\wsusoffline
* i.e. win7sp1x64-o2k10sp1-ie9
* optional step, can keep all updates in one folder if desired and just reference wsusoffline folder for rest of steps
* however, doing it this way keeps the amount of files copied to clients minimized
* doing this would require multiple runs of WSUS Offline, each time targeting different OS, etc and different target folder
4) Run UpdateGenerator.exe and select desired Windows & Office updates and options
* ex: Windows 7 SP1 x64, Office 2010 SP1
5) At the bottom under USB medium check "Copy updates for selected products into directory" and specify target
* ex: assuming Y: is mapped to \\fileserver\kace -> use Y:\Postinstalls\WSUSOffline\win7sp1x64-o2k10sp1-ie9
6) Click Start button to initiate downloads
* this will take a while to complete
* when completed, should see folder structure under Y:\Postinstalls\WSUSOffline\win7sp1x64-o2k10sp1-ie9 with UpdateInstaller.exe
7) Run UpdateInstaller.exe on target PC and review selections, make note of desired changes, then close
* ex: Install Office File Converters, Install Office File Validation, Automatic reboot and recall
8) Edit UpdateInstaller.ini to includue/exclude changes (per previous step)
* ex: instofc=Enabled, instofv=Enabled, autoreboot=Enabled
9) K2000 - During scripted install, copy the client-targeted folder to client & run Update.exe via AutoIT script.
Create a new Postinstallation Task - Application - Windows
Name: WSUS Offline (Win7)
Runtime Environment: Windows
Command Line: start /wait wsusoffline-win7.exe
Note - Originally had this setup the same way as the XP install (with WSUS Copy as a mid-level task),
but this mid-level task broke the "driver feed workaround" in K2000 v3.3. Possibly might work
with 3.4 but will have to wait and see. Until then was able to get progress bar, etc working.
________________________________________________________
Win7 AutoIT Script
* referenced in step 9
* compile this as wsusupdate-win7.exe and upload to K2000
* be sure to update the network share credentials (DriveMapAdd - towards end)
* be sure to update the path to the WSUS update files (_CopyWithProgress - towards end)
________________________________________________________
#CS
;~ This script is demonstrate copy process with custom designed progress displayed, the progress display details about the copy process.
;~
;~ Syntax: _CopyWithProgress("C:\Source", "C:\Dest", 1)
;~ First parm is the source dir that files will be copied from.
;~ Second param is the destination path that files will be copied to.
;~ If the last parameter set as 1, then all existing files will be replaced with copied ones.
;~
;~ Author: G.Sandler a.k.a CreatoR
;~ Functions _DirListToArray() and _FileListToArrayEx() is originaly writen by amel27.
#CE
#Region;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=..\..\..\WINDOWS\system32\RefreshLock.ico
#EndRegion;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>
#include <File.au3>
#include <Date.au3>
Func _CopyWithProgress($SourcePath, $DestPath, $Replace=0)
If Not FileExists($SourcePath) Then Return SetError(1, 0, -1)
If Not StringInStr(FileGetAttrib($DestPath), "D") And Not DirCreate($DestPath) Then Return SetError(2, 0, "")
If $Replace <> 0 And $Replace <> 1 Then SetError(3, 0, "")
Local $PathName = StringRegExpReplace($SourcePath, "^.*\\", "")
Local $Progress=0, $Counter, $ReadySize, $MidlePath, $Ready, $TimeRemained
Local $CurrentFilePath, $CurrentFileName, $CurrentFilePathName, $CurrentParentDirName
ProgressOn("Copy Files...", "Copy: " & $PathName, "Getting dir structure" & @LF & "Please wait...")
Local $TotalDirSize = DirGetSize($SourcePath)
Local $FilesArr = _FileListToArrayEx($SourcePath)
Local $FilesCount = UBound($FilesArr)-1
Local $ProgressStep = 100 / $FilesCount
If IsArray($FilesArr) Then
For $i = 1 To UBound($FilesArr)-1
$CurrentFilePath = $FilesArr[$i]
$CurrentFileName = StringRegExpReplace($CurrentFilePath, "^.*\\", "")
$CurrentFilePathName = StringReplace($CurrentFilePath, $SourcePath & "\", "")
$CurrentParentDirName = _GetParentDirName($CurrentFilePath)
$Progress += $ProgressStep
$Counter += 1
$ReadySize = FileGetSize($CurrentFilePath)
$MidlePath = _GetMidlePath($CurrentFilePath)
$Ready = $Counter & "/" & $FilesCount
$TimeRemained = _GetTimeRemained($TotalDirSize, $ReadySize, $FilesCount, $Counter)
ProgressSet($Progress, 'Copy... from "' & $CurrentParentDirName & '" to "' & $CurrentParentDirName & '"' & @LF & _
$MidlePath & @LF & "Approximate Time Remaining: " & $TimeRemained, "Ready: " & $Ready)
FileCopy($CurrentFilePath, $DestPath & "\" & $CurrentFilePathName, 8+$Replace)
Next
EndIf
ProgressOff()
EndFunc
Func _FileListToArrayEx($sPath, $sMask='*')
Local $i, $j, $blist, $rlist[1]=[0], $dlist = _DirListToArray($sPath)
_ArrayAdd ($dlist, $sPath)
For $i=1 To $dlist [0] +1
$blist = _FileListToArray ($dlist [$i], $sMask, 1)
If Not @error Then
For $j=1 To $blist [0]
_ArrayAdd ($rlist, $dlist[$i] & "\" & $blist [$j])
Next
EndIf
Next
$rlist [0] = UBound ($rlist) - 1
Return $rlist
EndFunc
Func _DirListToArray($sPath)
Local $rlist[2]=[1, $sPath], $blist, $alist=_FileListToArray ($sPath, '*', 2)
If IsArray ($alist) Then
For $i=1 To $alist [0]
_ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
$blist = _DirListToArray ($sPath & "\" & $alist [$i])
If $blist[0]>0 Then
For $j=1 To $blist [0]
_ArrayAdd ($rlist, $blist [$j])
Next
EndIf
Next
EndIf
$rlist[0] = UBound($rlist) - 1
Return $rlist
EndFunc
Func _GetMidlePath($sPath)
If StringLen($sPath) <= 50 Then Return $sPath
Local $StartPath = StringLeft($sPath, 25)
Local $EndPath = StringTrimLeft($sPath, StringInStr($sPath, "\", 0, -2)-1)
Return $StartPath & "..." & $EndPath
EndFunc
Func _GetParentDirName($FullName)
Local $LastSlashPos = StringInStr($FullName, "\", 0, -1)
Local $SecondLastSlashPos = StringInStr($FullName, "\", 0, -2)
Return StringMid($FullName, $SecondLastSlashPos+1, $LastSlashPos-$SecondLastSlashPos-1)
EndFunc
Func _GetTimeRemained($TotalSize, $CurrentSize, $FilesCount, $CurrentFilesCount)
Local $NumLevl = 0.5
If $TotalSize <= $CurrentSize Then Return _SecsToTime(0)
Switch $FilesCount - $CurrentFilesCount
Case 0 To 100
$NumLevl = 0.1
Case 100 To 1000
$NumLevl = 0.5
Case 1000 to 2000
$NumLevl = 1
Case Else
$NumLevl = 2
EndSwitch
$Secs = ($TotalSize * $NumLevl) / (3600 * $CurrentFilesCount) - ($CurrentSize * $NumLevl) / (3600 * $CurrentFilesCount)
Return _SecsToTime($Secs)
EndFunc
Func _SecsToTime($iTicks, $Delim=":")
If Number($iTicks) >= 0 Then
$iHours = Int($iTicks / 3600)
$iTicks = Mod($iTicks, 3600)
$iMins = Int($iTicks / 60)
$iSecs = Round(Mod($iTicks, 60))
If StringLen($iHours) = 1 Then $iHours = "0" & $iHours
If StringLen($iMins) = 1 Then $iMins = "0" & $iMins
If StringLen($iSecs) = 1 Then $iSecs = "0" & $iSecs
Return $iHours & $Delim & $iMins & $Delim & $iSecs
EndIf
Return SetError(1, 0, 0)
EndFunc
; Map X drive to \\myserver2\stuff2 using the user "jon" from "domainx" with password "tickle"
DriveMapAdd("O:", "\\fileserver\kace", 0, "domain\username", "password")
Sleep(10000)
_CopyWithProgress("o:\postinstalls\wsusoffline\win7sp1x64-o2k10sp1-ie9", "C:\KACE", 1)
; install updates
Run("c:\Kace\UpdateInstaller.exe")
WinWaitActive("WSUS Offline Update 7.3 - Installer")
ControlClick("WSUS Offline Update 7.3 - Installer", "Start", "Button24", "left", 1, 40, 12)
Sleep(100)
WinWaitActive("Administrator: C:\Windows\system32\cmd.exe")
;waits until no instance of cmd.exe exists
ProcessWaitClose("cmd.exe")
________________________________________________________
Hope that helps!
John
-
I'm trying to use this as a post install task with our Win7SP1 image and I keep getting an error from the K2000 that it cannot find the files, has any experienced this? (I know it's a generic thing to ask, but it's a complicated enough process that I'm having trouble pinning down where the issue is) - khorvath 10 years ago
Answers (5)
For anyone who wants to use this with 7.4, here's the updated section at the end (change in program window name and button). Just replace everything after ";install updates" above with this.
John
_________________________
; install updates
Run("c:\Kace\UpdateInstaller.exe")
WinWaitActive("WSUS Offline Update 7.4 - Installer")
ControlClick("WSUS Offline Update 7.4 - Installer", "Start", "Button25", "left", 1, 50, 15)
Sleep(100)
WinWaitActive("Administrator: C:\Windows\system32\cmd.exe")
;waits until no instance of cmd.exe exists
ProcessWaitClose("cmd.exe")
Comments:
-
Do you know if the ControlClick will work on WSUS Update8.4? - pcofer 11 years ago
-
At the very least, you'll have to change the window title to reflect version 8.4 and verify the ControlClick target using the AutoIt Window Info tool. If you aren't familiar with AutoIt, just go through the first two or three tutorials included in the AutoIt Help file and you should be set.
John - jverbosk 11 years ago -
Hi jverbosk, thanks so much for this excellent walkthrough. I'm using this with version 8.5 and it's working well (had to adjust the AutoIT script Button25 to Button26 for the new version.) I have a question though, I'm finding that putting this task at the end of my post-installation tasks is causing it to fail. I'm pretty sure it's because it goes to install IE9 (or any update that requires a restart), but upon restart KACE is jumping to the next step which is to do a CleanUp aka delete the c:\KACE folder. Are you adding a runonce to the end of this to yours? I would have thought that it would all be ok considering 'Auto-reboot and call' is checked... - anonymous_84852 11 years ago
-
richarhila,
The last time I used this (before I changed employers) was with version 7.4, so I can't speak specifically for version 8.5. But I can say that for my Windows 7 scripted installs, I had it set as the very last postinstallation task (without anything else added). For my Windows XP scripted installs, I had it run after deploying MS apps (Office, IE) and had a "buffer for reboot" and "sleep" task run directly after (prior to further postinstallation task installs, like Adobe Reader, Adobe Flash, Java, etc). For reference, here are how those two tasks were setup:
Buffer for Reboot
Type: BAT Script
Runtime Environment: Windows
BAT Script: ping loopback -n 60
Sleep
Type: Application
Runtime Environment: Windows
File: ksleep32.exe
Command Line: ksleep32.exe 60
More info on using these can be found in this post I did:
http://www.itninja.com/question/reboots-during-postinstallation-tasks
I also used the postinstall task converter, something which I found absolutely necessary for my Windows 7 scripted installs:
http://www.itninja.com/blog/view/k2000-postinstall-task-converter
Beyond that, I would suggest building a very simple scripted install which only has the WSUS Offline postinstall task run, so that you can isolate it. I remember playing with the automatic reboot option when I was initially testing and at one point was using a separate reboot postinstall task to initiate the reboot. You might consider giving this a shot as well, although you'll probably have to play with the timing of the reboot task (i.e. the specified time) to get it right.
Well, hopefully something there will get you pointed in the right direction, and when you are able to get it working - please share your solution so others may benefit as well. ^_^
John - jverbosk 11 years ago
For anyone who wants to use this with 7.5, here's the updated section at the end (change in program window name and button). Just replace everything after ";install updates" above with this.
John
_________________________
; install updates
Run("c:\Kace\UpdateInstaller.exe")
WinWaitActive("WSUS Offline Update 7.5 - Installer")
ControlClick("WSUS Offline Update 7.5 - Installer", "", "Button25", "left", 1, 40, 12)
Sleep(100)
WinWaitActive("Administrator: C:\Windows\system32\cmd.exe")
;waits until no instance of cmd.exe exists
ProcessWaitClose("cmd.exe")
Comments:
-
Thank you for recommending this article! I will try this as an alternative to post install windows updates. I will probably be reaching out with questions! - Tomsquatch 11 years ago
A user contacted me directly about an issue with this, so I'm sharing the question and my reply in case it might help others.
John
_____________________________
Hi John,
I hope you can provide some help regarding WSUS Offline as postinstallation task.
http://www.itninja.com/question/wsus-offline-as-postinstallation-task-xp-win7-w-progress-bar
Basucally I have followed you article (Windows 7), and for some reason our deployment gets stuck on a cmd screen.
I have followed all steps, created the au3 script and compiled as exe
I have changed only the below in BOLD:
; Map X drive to \\myserver2\stuff2 using the user "jon" from "domainx" with password "tickle"
DriveMapAdd("O:", "\\IP address\updates", 0, "mydomain\myadmin", "myadminpassword")
Sleep(10000)
_CopyWithProgress("o:\win7x86", "C:\KACE", 1)
; install updates
Run("c:\Kace\UpdateInstaller.exe")
WinWaitActive("WSUS Offline Update 8.6 - Installer")
ControlClick("WSUS Offline Update 8.6 - Installer", "Start", "Button24", "left", 1, 40, 12)
Sleep(100)
WinWaitActive("Administrator: C:\Windows\system32\cmd.exe")
;waits until no instance of cmd.exe exists
ProcessWaitClose("cmd.exe")
_____________________________
My suggestions:
Comments:
-
I'm currently using 9.3.1 for Windows 7 and Office 2013 but have had to download 9.2.1 for Office 2003 as we're using Access 2003 for some in-house applications. Once the files are downloaded, can I go through and delete the updates that aren't needed? I'd like to only keep the updates that apply to Office 2003 as a whole and Access 2003. I don't need Word/PPT/Outlook, or other updates. - eightondbrk 10 years ago
so that the conversation will remain readable.