Video Screencast Help
Symantec to Separate Into Two Focused, Industry-Leading Technology Companies. Learn more.
Endpoint Management Community Blog

A Control Freak's Guide to Windows 7 Deployment (Part 2)

Created: 18 Apr 2011 • Updated: 27 Apr 2011
MurrayW's picture
+2 2 Votes
Login to vote

This is Part 2...

In this next part of my "Control Freak" approach to deploying "Windows 7", I thought I would cover off on the main sections of my deployment and start to provide you with my scripts that make it all work. So here goes: My deployment, when made generic for the purpose of this blog, can be as little as three tasks in a Deployment Server job. In my previous blog I described the process of generating the "Unattend.XML" file with variables and database lookups, and after that we have a disk image task, and then the stuff that follows to make it all work. In this blog entry I will concentrate on the third part. Now, I did describe the creation of the "Fix BCD" commands in the previous blog as well, but bare with me here as I run through that and the rest of the script processes.
 
Now, one unexpected gotcha I faced when writing these scripts is allowing them all to use the detected drive letters etc. Now, admittedly, some of these may have been avoided if I wasn't so determined to use batch scripting. In case you are not familiar with the issues, here are some points;
 
  1. Each command window is volatile - If you try to set an environment variable within a script, when using WinPE, that variable will only exist as long as that command window (or script) is running. The moment the script exists, the variables it created during that session are purged. As such, you cannot detect something and use a "SET variable_name=value" and use that in later scripts... it doesn't work.
     
  2. Registry-Set variables do not appear - A common "why don't you" answer to a lot of these WinPE variable issues is to set them in the Session Manager registry. The only problem with this is that they won't load until you reload the environment... which kind of makes them pointless. There is no way I can find that will allow WinPE to reload it's session settings (environment variables, etc) without causing the DAgent to exit the session, or lose access to the variables the moment you try running a command anyway (see point 1 above).
     
  3. Using command arguments - This is another common "answer" without actually providing an answer. You need to be careful about how you both set and deal with command-line argument in "batch world", because spaces will cause a single command line argument t become many, and use of quotes need to be replicated in the IF statement when checking them, otherwise they won't match. This is also only useful if you don't plan on expanding your scripts or changing variable names etc. To simplify things, I prefer the following approach...
     
  4. Nested and CALL'ed Batch Scripts - In the end I found that a child batch file can actually read any environment variables set by the parent batch file, so long as you set them first. This also lets you perform error checking and re-dos. It also allows you to split up an unwieldy script in to multiple parts so that you don't hit the "Run Script" maximum character limit, and makes further editing a lot simpler.
So here is an example of my deployment script that I use within automation but post-image. NOTE: For making this easier to follow, I have removed several processes we perform, and made this a single script instead of my sub-script process. As it is, this script is probably too long to work within a single "Run Script" window of DS.
 
 
@ECHO OFF
REM ### Apply system and deployment configuration...
CLS
ECHO    _____ __             __  _                
ECHO   / ___// /_____ ______/ /_(_)___  ____ _    
ECHO   \__ \/ __/ __ `/ ___/ __/ / __ \/ __ `/    
ECHO  ___/ / /_/ /_/ / /  / /_/ / / / / /_/ / _ _ 
ECHO /____/\__/\__,_/_/   \__/_/_/ /_/\__, (_/_/_)
ECHO                                 /____/    
ECHO.
REM ###########################################
REM Set variables for this deployment...
SET ___Drive.AR=x86
REM ###########################################
ECHO Detecting Drive Volumes...
SET ___Drive.SR=
SET ___Drive.OS=
SET ___Drive.ID=%ID%
FOR %%V in (C D E G H I J K L M N P Q T U V W Y Z) DO (
  ::: Check for the bootmgr to designate this volume as the "System Reserved"...
  IF EXIST "%%V:\bootmgr" (
    ECHO   * System Reserved Volume Found at %%V:
    set ___Drive.SR=%%V:
  )
  ::: Check for the "Explorer.exe" to designate this volume as the "System"...
  IF EXIST "%%V:\Windows\Explorer.exe" (
    ECHO   * OS Volume Found at %%V:
    set ___Drive.OS=%%V:
  )
)
ECHO.
REM -------------------------------------------------------------------------------
REM ### Configure System - Step 1 of 4 (BCD Config)...
CLS
ECHO     ____              __     ______            _____          
ECHO    / __ )____  ____  / /_   / ____/___  ____  / __(_)___ _    
ECHO   / __  / __ \/ __ \/ __/  / /   / __ \/ __ \/ /_/ / __ `/    
ECHO  / /_/ / /_/ / /_/ / /_   / /___/ /_/ / / / / __/ / /_/ /._ _ 
ECHO /_____/\____/\____/\__/   \____/\____/_/ /_/_/ /_/\__, (_/_/_)
ECHO                                                  /____/     
ECHO Configuring Boot Configuration...
ECHO  * Setting default partition to %___Drive.OS%...
%SYSTEMROOT%/system32/Bcdedit.exe /set {default} device partition=%___Drive.OS% >NUL
ECHO  * Setting boot OS partition to %___Drive.OS%...
%SYSTEMROOT%/system32/Bcdedit.exe /set {default} osdevice partition=%___Drive.OS% >NUL
ECHO  * Setting Boot Manager partition to %___Drive.SR%...
%SYSTEMROOT%/system32/Bcdedit.exe /set {bootmgr} device partition=%___Drive.SR% >NUL
ECHO.
ping -n 5 127.0.0.1 > nul
REM -------------------------------------------------------------------------------
REM ### Configure System - Step 2 of 4 (Config Scripts)...
CLS
ECHO    _____               ______            _____          
ECHO   / ___/__  _______   / ____/___  ____  / __(_)___ _    
ECHO   \__ \/ / / / ___/  / /   / __ \/ __ \/ /_/ / __ `/    
ECHO  ___/ / /_/ (__  )  / /___/ /_/ / / / / __/ / /_/ /._ _ 
ECHO /____/\__, /____/   \____/\____/_/ /_/_/ /_/\__, (_/_/_)
ECHO      /____/                                /____/       
ECHO Installing deployment files, scripts, and configurations...
REM ### Copy across the config scripts...
ECHO.
ECHO Injecting Windows Deployment Configuration File for System...
IF NOT EXIST "%___Drive.OS%\Windows\Panther\Unattend" ( 
  ECHO  * Creating "Unattend" folder: %___Drive.OS%\Windows\Panther\Unattend
  MD "%___Drive.OS%\Windows\Panther\Unattend" 
)
IF NOT EXIST "%___Drive.OS%\Windows\Setup\Scripts" ( 
  ECHO  * Creating "Scripts" folder: %___Drive.OS%\Windows\Setup\Scripts...
  MD "%___Drive.OS%\Windows\Setup\Scripts"
)
IF NOT EXIST "%___Drive.OS%\Sysprep" ( 
  ECHO  * Creating "Sysprep" folder: %___Drive.OS%\Sysprep...
  MD "%___Drive.OS%\Sysprep" 
)
ECHO  * Copying configuration XML to: %___Drive.OS%\Windows\Panther\Unattend...
COPY /Y "R:\Temp\%ID%_Unattend.xml" "%___Drive.OS%\Windows\Panther\Unattend\Unattend.xml" >NUL
ECHO  * Copying automation scripts to %___Drive.OS%\SYSPREP...
COPY /Y "R:\Deploy\Scripts\Config_Scripts\W7\Model_Setup.vbs" "%___Drive.OS%\SYSPREP\Model_Setup.vbs" >NUL
COPY /Y "R:\Deploy\Scripts\Config_Scripts\W7\ProgressBar.vbs" "%___Drive.OS%\SYSPREP\ProgressBar.vbs" >NUL
REM ### Copy across the Altiris Agent...
ECHO.
ECHO Preparing Altiris Deployment Agent for System...
IF "%___Drive.AR%"=="x64" (
  ECHO  * Copying Altiris Deployment Agent Setup [x64]...
  COPY /Y "R:\Agents\Aclient\Dagent_x64.msi" "%___Drive.OS%\SYSPREP\Dagent_x64.msi" >NUL
) ELSE (
  ECHO  * Copying Altiris Deployment Agent Setup [x86]...
  COPY /Y "R:\Agents\Aclient\Dagent.msi" "%___Drive.OS%\SYSPREP\Dagent.msi" >NUL
)
ECHO  * Copying Altiris Configuration and Installer Handler...
COPY /Y "R:\Deploy\Scripts\Config_Scripts\W7\Dagent_Installer.vbs" "%___Drive.OS%\SYSPREP\Dagent_Installer.vbs" >NUL
REM ### Copy across the finalising script...
ECHO.
ECHO Injecting Deployment Finishing Script for System...
ECHO  * Copying Windows Setup Scripts...
COPY /Y "R:\Deploy\Scripts\Config_Scripts\W7\SetupComplete.cmd" "%___Drive.OS%\Windows\Setup\Scripts\SetupComplete.cmd" >NUL
ECHO.
ping -n 5 127.0.0.1 > nul
REM -------------------------------------------------------------------------------
REM ### Configure System - Step 3 of 4 (Drivers)...
CLS
ECHO     ____       _                         
ECHO    / __ \_____(_)   _____  __________    
ECHO   / / / / ___/ / ] / / _ \/ ___/ ___/    
ECHO  / /_/ / /  / /[ ]/ /  __/ /  (__  )._ _ 
ECHO /_____/_/  /_/ [___/\___/_/  /____(_/_/_)
ECHO. 
ECHO Copying System Drivers for SYSPREP...
CSCRIPT //Nologo "R:\Deploy\Scripts\Config_Scripts\W7\Build_Driver_List.vbs" %___Drive.AR%
ECHO.
ping -n 5 127.0.0.1 > nul
REM -------------------------------------------------------------------------------
REM ### Configure System - Step 4 of 4 (Extra Files)...
CLS
ECHO     _______       _      __    _                
ECHO    / ____(_)___  (_)____/ /_  (_)___  ____ _    
ECHO   / /_  / / __ \/ / ___/ __ \/ / __ \/ __ `/    
ECHO  / __/ / / / / / (__  ) / / / / / / / /_/ /._ _ 
ECHO /_/   /_/_/ /_/_/____/_/ /_/_/_/ /_/\__, (_/_/_)
ECHO                                    /____/       
ECHO Copying Files and Updates to System...
REM ### Check to see if a SYSTEM update is required...
ECHO  * Checking for SYSTEM updates...
IF EXIST "%___Drive.OS%\SYSPREP\UpdateSystem.dat" (
  ECHO  * Adding Offline Drivers and Configuration Settings...
  REM ::: Load the Offline SYSTEM hive to make it editable...
  REG LOAD HKLM\OfflineSystem "%___Drive.OS%\Windows\System32\Config\SYSTEM" >NUL
  REM ::: Import the updated SYSTEM settings...
  REG IMPORT "%___Drive.OS%\SYSPREP\UpdateSystem.dat" >NUL
  REM :: Unload the modified SYSTEM hive ready for use...
  REG UNLOAD HKLM\OfflineSystem >NUL
)
REM ### Check to see if a SOFTWARE update is required...
ECHO  * Checking for SOFTWARE updates...
IF EXIST "%___Drive.OS%\SYSPREP\UpdateSoftware.dat" (
  ECHO  * Adding Offline Computer Settings...
  REM ::: Load the Offline SOFTWARE hive to make it editable...
  REG LOAD HKLM\OfflineSoftware "%___Drive.OS%\Windows\System32\Config\SOFTWARE" >NUL
  REM ::: Import the updated SOFTWARE settings...
  REG IMPORT "D:\SYSPREP\UpdateSoftware.dat" >NUL
  REM :: Unload the modified SYSTEM hive ready for use...
  REG UNLOAD HKLM\OfflineSoftware >NUL
)
ECHO.
ping -n 5 127.0.0.1 > nul
REM -------------------------------------------------------------------------------
REM ### Finish the script and clear the variables...
SET ___Drive.SR=
SET ___Drive.OS=
SET ___Drive.AR=
SET ___Drive.ID=
 
To more accurately reproduce my working script, cut each section starting with dashes and paste it into it's own CMD file. Replace this in the main script with a line like the following:
 
CALL "R:\Deploy\Scripts\Setup_Part-1_Boot.cmd"
 
The magic here is simply setting environment variables. For this script example we use four, however, my production script uses a few ore than this. The values are;
 
  • "___Drive.AR" - This is the architecture value we can either detect or set per image job. For this example I have added a hard-coded value of "x86". Whether you turn this into a variable is up to you, but generally as you'll define an x86 and x64 deployment job, setting this one property is probably not too difficult. You could also use an "IF" statement to check for the WinPE architecture, or for 64-Bit-only files deployed by the "Distribute Disk Image" task.
     
  • "___Drive.SR" - Using simple FOR and IF commands in the main part of the script, we set this variable to the volume letter that contains the "BOOTMGR" file. This will then be referenced as the "System Reserved" partition. If your disk image doesn't have a "System Reserved" partition, it will most likely have the "BOOTMGR" on the OS volume letter, and this variable will therefore be set to that location automatically.
     
  • "___Drive.OS" - Using the same process as above, this variable represents the drive letter that contains the explorer executable. It's worth noting here why I chose this condition: If you look carefully I am excluding the drive letters where the DS WinPE drives would be, which leaves only the host drives. I then check for a file that is almost certainly only present on a Windows installation. I then only take the first occurrence of this, which should mean that one of the primary disk contained the file, and therefore the Windows OS. You can feel free to substitute this with other detection methods or files, but this works for us.
     
  • "___Drive.ID" - This variable is a simple way for us to transfer the DS "%ID%" variable to an environment variable so that the sub-scripts can access it. This is used in the "Sys Config" script to locate and transfer the "Unattend.XML" to the system, so if pretty important, but as you read earlier, it can get lost during operations you'd normally assume would work (i.e. second command script window).
 
Now, I guess I need to explain what this script does and what all the called/referenced scripts actually do, so here goes:
 
 

Part 1 - Starting

This "Starting" section is pretty much what I explained both above and in my previous blog post. It's all about gathering information (Computer ID, System Reserved driver letter, OS drive letter and architecture) and storing these in a way that can be accessed by other scripts without the need to repeat the detection processes. This takes an "AR" variable for the architecture, the "%ID%" variable for the Computer ID, and then looks through all the drive letters  with some exceptions. The excluded drive letters are;
 
  • "F:" - The default mapping for the "eXpress" share.
  • "O:" - Not used in this script, but this is where we set the optical drive (if present) using VBScript.
  • "R:" - Our new mapping for "eXpress", which avoids issues with computers with many drives/volumes these days.
  • "S:" - Another mapping to a volume on the server where we store drivers and settings for each model, etc.
  • "X:" - The default RAMDRIVE location for WinPE when loaded.

That's it. We set these variables and then just move on.

 

Part 2 - Boot Config

This is pretty basic and was covered in the previous blog as well. We simply use the detected "SR" and "OS" variables to set the required commands for "BCDEdit" in order to get the computer to actually boot. After the image process. We tell the system what volume the "BOOTMGR" is on, then what volume the "Windows" installation is on, and then set the "Windows" volume as the default boot option. Simple. Moving right along.
 
 

Part 3 - Sys Config

In this section, we expand a little on what was covered in the previous blog post. What we need to do is ensure the required folders for our deployment are in place. I simply run through a few IF statements and MD (make directory) commands to ensure everything is good. The important folders are;
 
  • "C:\Windows\Panther\Unattend" - Is where the "Unattend.XML" needs to live to be found automatically by Windows.
  • "C:\Windows\Setup\Scripts" - Is where the "SetupComplete.CMD" needs to live to be used by Sysprep.
  • "C:\SYSPREP" - Is a temporary folder location that we use to handle our registry edits, scripts, and drivers.
Following the folder creation we ensure the following file structure is made via copy commands.
 
  1. "C:\Windows\Panther\Unattend"
  • "Unattend.xml"
     
  1. "C:\Windows\Setup\Scripts"
  • "SetupComplete.cmd"
     
  1. "C:\SYSPREP"
  • "Model_Setup.vbs"
  • "ProgressBar.vbs"
  • "Dagent_x64.msi" or "Dagent.msi" depending on architecture
  • "Dagent_Installer.vbs"
 
Of these, the "unattend.XML" is the file generated and copied as part of an earlier process (see the previous blog post), and the "DAgent" files should be fairly self-explanatory. It's worth pointing out here that the "SetupComplete.CMD" is a part of the SYSPREP process and can contain any scripts or commands that you want to deploy to the system (bypassing UAC), which occurs after the SYSPREP/OOBE process, but prior to the first user logon screen. It needs that name, and to be in the location above, then it just works.
 
As for the other scripts:
 
  • "Dagent_Installer.vbs" - Is a script that inserts required registry values for our default agent install and then executes the copied MSI for the rest of the installation. I'll show you this script later on.
     
  • "ProgressBar.vbs" - Is a script that uses the IE rendering engine to display a bouncing-box progress bar for while the scripts in the "setupcomplete.cmd" are running. Normally, this is just a black screen. Without some sort of on-screen notification, we've had a few people think the computer is "broken" and reboot it - which breaks the deployment. I'll show you this script later on.
     
  • "Model_Setup.vbs" - If the main script and brains behind our hardware-independent imaging approach. It's a handler script that takes input arrays from a model-specific configuration file and will handle the silent installation of all drivers and utilities for each model and the post-install cleanup actions. This ties in with a few other scripts, so will probably be in Part 3 of this blog. Sorry :)
 

Part 4 - Drivers

Before we can execute the "Model Setup" script above, we need to figure out what model we are deploying to, whether we have a network repository of drivers available for it, and if we do, we need all those drivers, utilities, registry patches, and installer configuration files sent down to the computer. The way we have designed the network repository is that we have sub-folders for "x86" and "x64" content, and we use the "AR" variable set earlier to use as a  parameter for the "Build_Driver_List.vbs" script.
 
The script itself isn't anything to flash, it simply connects to the computer using a WMI call and returns the model number value. It then does a compare of this against a network location. If a model folder is not found, the script will exit and and the deployment will continue. The later "Model Setup" script will detect that no drivers were copied and will just exit. This allows you to fully deploy a computer using Windows-only drivers without actually preparing a network repository for it. This process is handy in working out what drivers and utilities you actually need to include to get the computer working.
 
 

Part 5 - Finishing

Here's another bit of magic needed for hardware independent imaging. Now, while users of the WIM format for disk images can potentially use the DISM tool to inject drivers for unsupported devices (and allow the continuance of the hardware independent imaging process), the IMG format is a little harder. While you could also re-deploy your base image to this computer, install drivers, and then rely on SYSPREP (again) to clean things up, I find that approach "dirty". I like my image completely devoid of drivers that aren't in-built Windows drivers. This, however, presents a problem. You see, we use SYSPREP to do a lot of heavy lifting here. We expect it to boot the computer, which may require mass storage controller drivers, and then we expect it to add the computer to the domain, which requires an installed/supported network card. So what if these devices don't have native in-built drivers? Well, we need to ask SYSPREP to do a little more for us. Here's how:
 
  1. If you remember all the way back to my previous blog post and the "Unattend.XML" file I provided, you'll probably have noticed that I included three "<DriverPaths>" entries within the "OfflineServicing" pass. These folders were "C:\SYSPREP\DRV_MSD", "C:\SYSPREP\DRV_NET" and "C:\SYSPREP\DRV_VIDEO". There is no harm in supplying these values, and also no harm if any or all of these folders don't actually exist. In this case, we use this to assist us with troublesome hardware if the need arises.
     
  2. The second part of the equation is the Windows registry. You see, while the "DriverPaths" value looks the business, and is explained away as being the way to install drivers, what we find is that Windows is a little dumber than that and actually needs the driver paths defined in the registry as well. So, to make this part easier, I have a template file called "UpdateSoftware.dat" that I use. This isn't anything too fancy. In fact, it's a registry file that simply contains the "DevicePath" expanding string registry value that is preset to the paths we already have in the "Unattend.xml" file. The file, by default, looks like this:
     
Windows Registry Editor Version 5.00
 
[HKEY_LOCAL_MACHINE\OfflineSoftware\Microsoft\Windows\CurrentVersion]
"DevicePath"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,\
  00,74,00,25,00,5c,00,69,00,6e,00,66,00,3b,00,43,00,3a,00,5c,00,53,00,59,00,\
  53,00,50,00,52,00,45,00,50,00,5c,00,44,00,52,00,56,00,5f,00,4e,00,45,00,54,\
  00,3b,00,00,00
 
Obviously, if any further "Software" hive entries are needed to make a computer work correctly (or if you need to patch something you found wrong with an earlier deployment), you can simply export the desired registry keys and copy the contents into this file - substituting the generic "Software" key name for the computer with "OfflineSoftware" to allow the import to function.
 
NOTE: You see, when dealing with "REGEDIT" within WinPE, the registry you can load is actually the WinPE registry. To load a value into the host Windows install, you need to mount the hive directly as another name which will appear as a subkey. In the example above, we are loading the host computer's registry as "OfflineSoftware" as a key into the "HKEY_LOCAL_MACHINE" key on WinPE. Neat, right?
 
  1. So, if your computer model needs some extra loving to make it work correctly, we copy this "UpdateSoftware.dat" file into the "SYSPREP" folder on the host. If present, the "Finishing" script process will load it into the host system's Windows registry hive ready for a reboot into production. Nice!
     
  2. Now the most important step, the actual driver that is required. For that we use a great little freeware tool called "Driver Magician Lite" (http://www.drivermagician.com/Lite.htm). This little program (I use the portable one) allows you to install drivers on a host Windows installation and then extract only the INF, CAT, SYS, DLL, and EXE files required to make the driver function. The software extracts these straight from the system and stores them in a nice export folder for you. To make use of these, we copy them, say a network driver, into the "SYSPREP" folder for "DRV_NET" and make sure we include the "UpdateSoftware.dat" file above.
 
Windows will then have enough information (and driver files) to handle the initial part of SYSPREP and get the computer on the domain, etc. After this process (the OOBE) completes, we can then use the "Model Setup" script to handle the full driver/utility installation (if required).
 
 

Addendum (A) - SetupComplete

Now, the part you don't see above is what actually calls all the scripts and processes at the end. This is a process that is handled by the "SetupComplete.CMD" file. As stated earlier, this is a file built into the Windows deployment process, and if it exists in the correct folder, during the SYSPREP process, it is executed and all contents are run (bypassing UAC) at the end of the OOBE process and prior to a user logon session being established. This is where I set up tyhe progress bar, initialise the "Model Setup" process, schedule a WINSAT hardware assessment to enable Aero, and install/configure the DAgent so that the rest of the deployment process (if there is anything else) can continue. Below is a copy of my "SetupComplete.CMD" file:
 
REM ### Execute Waiting Interface...
IF EXIST "C:\SYSPREP\ProgressBar.vbs" (
  START /B CMD /C WSCRIPT "C:\SYSPREP\ProgressBar.vbs"
)
 
REM ### Prepare the post-image config log file...
ECHO ################################## > "C:\Program Files\MySite\SYSinstall.log"
ECHO MySite - Windows 7 Setup Log  >> "C:\Program Files\MySite\SYSinstall.log"
DATE /T >> "C:\Program Files\MySite\SYSinstall.log"
TIME /T >> "C:\Program Files\MySite\SYSinstall.log"
ECHO ################################## >> "C:\Program Files\MySite\SYSinstall.log"
 
ECHO. >> "C:\Program Files\MySite\SYSinstall.log"
ECHO INSTALLING DRIVERS AND UTILITIES: >> "C:\Program Files\MySite\SYSinstall.log"
IF EXIST "C:\SYSPREP\Model_Setup.vbs" (
  START /B /WAIT WSCRIPT "C:\SYSPREP\Model_Setup.vbs"
) ELSE (
  ECHO No Driver Installer found, skipping... >> "C:\Program Files\MySite\SYSinstall.log"
)
 
ECHO. >> "C:\Program Files\MySite\SYSinstall.log"
ECHO SCHEDULED FIRST RUN HARDWARE ASSESSMENT: >> "C:\Program Files\MySite\SYSinstall.log"
REG ADD "HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce" /v "WinSAT Exec" /t "REG_SZ" /d "\"C:\Windows
 
\System32\WinSAT.exe\" dwm" /f
 
ECHO. >> "C:\Program Files\MySite\SYSinstall.log"
ECHO INSTALLING ALTIRIS AGENT: >> "C:\Program Files\MySite\SYSinstall.log"
IF EXIST "C:\SYSPREP\Dagent_Installer.vbs" (
  START /B /WAIT WSCRIPT "C:\SYSPREP\Dagent_Installer.vbs"
) ELSE (
  ECHO No DAgent Installer found, skipping... >> "C:\Program Files\MySite\SYSinstall.log"
)
 
NOTE: You can see the use of "START" commands intermediate "CMD" calls and the lack of "ECHO OFF" statement for this script. I have found that these, and direct calls to "MSIEXEC" can break the process. The above configuration is the only way I have had it work reliably.
 
 

Addendum (B) - What Next?

Well, as you can see from the script above, I am logging the process as I go. What you don't see is that I also log each individual action within the VBScripts. Not only is this handy for figuring out what went wrong, but allows us to be notified of any deployment issues within the status of the DS job. I do this by using another couple of tasks beyond the three we're discussing. I use one that will purge the "SYSPREP" folder, and another called "Check_Install_Status.VBS" which looks like this:
 
OPTION EXPLICIT
'### Check the status of the "SYSinstall.log"...
'###################################################################
'
' STATUS CHECKER SCRIPT v0.1
' -----------------------------
'
' The purpose of this script is to check for and read the setup log
' file for "Windows 7" installations ("SYSinstall.log") and check
' whether any errors have occured during the driver and utility
' setup process.
'
' When run through the Altiris Deployment Server, this script will
' return a 404 error if the setup log is missing completely, and 
' will return a 1603 "fatal error" if it finds any installation
' errors in the log. At this point, a technician can remotely access
' the log file and see what failed, and then perform the required
' installation manually (or as a deployment job).
'
' This script takes advantage of the newly modified "Model_Setup"
' script error reporting strings.
'
' Written by Murray Webber (24/08/2010)
'
'###################################################################
 
'### Define script variables and objects...
DIM objFSO, LogFile, objFileData
SET objFSO = CreateObject("Scripting.FileSystemObject")
CONST ForReading = 1
LogFile = "C:\Program Files\MySite\SYSinstall.log"
 
'-------------------------------------------------------------------
 
'### Check that the log file is present...
If NOT objFSO.FileExists(LogFile) Then
  Wscript.Quit(404)
End If
 
'### Now check the files contents...
objFileData = objFSO.OpenTextFile(LogFile, ForReading).ReadAll
If INSTR(objFileData, "ERROR") Then
  wscript.echo "Found Errors!"
  wscript.Quit(1603)
End If
 
 
'-------------------------------------------------------------------
 
'### Clear the variables and exit...
SET objFSO = nothing
SET LogFile = nothing
SET objFileData = nothing
 
Now, partly because I can't spend too much time on this, partly that I don't want this post to be too code-heavy, and partly because this is already massively long... I will leave the setup of the network driver repository, "Build Driver List" script, the "Model Setup" script, and the use of the configuration file for the hardware independent imaging process, all for the next installment of the "Control Freak" blog posts. What I will show you below is the contents of the "DAgent Installer" and "Progress Bar" scripts, and that will have to do for now.
 
  • "DAgent_Installer.VBS" - See below for example. NOTE: You'll need to edit a lot of this to match your own environment. Start with the "******" lines and then make sure that all the register values are correct.
     
  • "ProgressBar.VBS" - In all it's incredibly boring glory. Hey, it serves it's purpose!
     

Thanks for reading. Next time we'll do the cool hardware independent stuff.

Final Words

Thanks for reading my blog. Please note that, although I have written these scripts for use in our production environment, and they work fine here, this sub-set of script provided in the blog have not been completely tested and may not work correctly in your environment. As with everything, please try to understand what the code is doing and test in a non-production environment first. Neither my employer or I will accept any responsibility for the (mis)use of these scripts and do not claim that they are a final production-ready solution. If the scripts or ideas presented here do help you, then please drop me a comment, email, and.or PM to let me know.