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

1 Comment   [ + ] Show Comment

Comments

  • This content is currently hidden from public view.
    Reason: Removed by member request
    For more information, visit our FAQ's.
  • 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)
Please log in to comment

Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.

Answers

1

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")

Answered 08/13/2012 by: jverbosk
Red Belt

  • Do you know if the ControlClick will work on WSUS Update8.4?
  • 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
  • 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...
    • 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
Please log in to comment
1

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")

Answered 12/06/2012 by: jverbosk
Red Belt

  • 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!
Please log in to comment
0

You should totally repost this under Blogs. Great write up and thank you!

Answered 01/14/2013 by: aaronr
Green Belt

Please log in to comment
0

Hi, I have followed your article and made the changes in the script...However upon deployment I only get a cmd screen. I think there are no logs files I can check.

Can someone provide help?

thanks in advance 

Answered 10/08/2013 by: rgreg
Orange Belt

Please log in to comment
0

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:


The first thing you will need to determine is where it is failing - is it failing when trying to copy files to the target machine, or is it failing when trying to launch WSUS Offline Update installer?  You should be able to determine this by opening Task Manager, launching explorer.exe, browsing to C:\KACE and checking to see if the C:\KACE folder has the WSUS Offline files present or not.
 
If things are failing during the copy process, you might need to double-check access to your shares.  Same idea here, open Task Manager, launch another command prompt window, and try to manually map to the share with NET USE.  If that works fine, play with the copy command.
 
If things are failing at the WSUS Offline Update installer step, you'll probably need to break this section out and troubleshoot this part of the script manually using AutoIT to determine if one of the ControlClick variables changed.  If you are unfamiliar with AutoIT, I highly suggest stepping through the tutorial to familiarize yourself with the AutoIT Window Info app (which is what you will use to determine these variables).  As with any postinstall task, you'll want to make sure things are working outside of the K2000 deployment environment before setting it up as a postinstall task (lots of trial and error here, I have found and when the program changes, the process sometimes need repeated to determine how to get the newer version working).
 
If both of those are looking good (i.e. files copying down fine, WSUS Offline installer process running fine), you may need to tweak either the WSUS Offline options or the scripted install to handle the reboot.  I just posted an comment regarding this on the ITNinja page you referenced here, so hopefully something there will help you with that process.
 
Hope that helps!
 
John
Answered 10/08/2013 by: jverbosk
Red Belt

  • 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.
Please log in to comment
Answer this question or Comment on this question for clarity