Share This Post

Fully Automate Your Quarterly Build & Capture Process

Best practices has your desktop deployment not installing Windows via the setup.exe each and every time, but rather deploying a captured Windows image and building off of that. You choice of a thin or fat image is up to you and your environmental needs, but periodically executing a Build & Capture (B&C) routine that installs Windows and all the latest service packs and hotfixes is the best way to keep your new builds fresh and the deployment time down.

But lets face it – those well crafted methodologies put into place which had you spinning off a new WIM quarterly have been collecting dust since implementation. Not that you don’t want to do it, and not that you probably haven’t pushed an update when you tire of fielding the growing complaints about how long the build is taking while Windows installs update, but you’re just really not doing it regularly. The most common reason I hear is that they just forget to do it (not unreasonable as a lot can happen in 3 months). If remembering, or finding the time to do it are the reasons your B&C isn’t happening on a regular basis, it’s time to let the machines take over the task.

For this article, I’ll cover how to completely automate your B&C WIM refresh. This article’s environment utilizes Windows Server 2012 and Hyper-V, SCCM 2012 SP1, and PowerShell. It is completely possible to adjust this process to match your environment.

SCCM Setup

Configuring Your B&C Task Sequence

A complete coverage of how to create a B&C Task Sequence (TS) is beyond the scope of this article, but I’ll cover the basics of what your TS should look like.

  • VM Platform. Your B&C should be as generic as possible, with only the few drivers integrated into the installation as needed for network connectivity. Your TS should also only be creating a single partition.
  • Always assume a Bare Metal (New Computer) build. Obviously, as you are capturing a Windows installation which will serve as the foundation for all workstations, you want it to be as clean as possible. This means that you are not performing a refresh build, nor are you concerned with the build after the capture has completed.
  • Make it Zero Touch. Full automation is required for this to work. Do not create a User Driven Installation (UDI), or an installation that pauses to allow you to do something: 100% hands-off.

Document the capture destination. The “Capture the Reference Machine” step in your build specifies the UNC and WIM file name for the captured image. Document these as you will need to reference them within your automation later.

There is one non-standard step needed in your task sequence, and that is to actually shutdown the VM. If your B&C TS just ends with the “Capture the Reference Machine” command (or the capture logs on error steps), the computer is just going to reboot and start the Windows mini-setup. That is fine for an attended capture as you’d just be powering it off and disposing of it, but for full automation, we want the VM to actually power down. That way, our managing automation will know when the capture has completed, and can then move on to clean-up and other desired tasks. Create a new Run Command Line task at the very end of your TS with the command line as follows:

wpeutil.exe shutdown

Create A Target Collection

A B&C TS is very specific and limited in it’s target audience. It isn’t something that you want all people to see, nor is it really something you want exposed to every hardware platform (as your target platform is a VM). The best way to limit the TS to just an approved hardware platform is to first identify what hardware is approved to run the TS, then create a direct membership collection which contains those objects. As you’re not making the TS available to Unknown Computers, your target hardware must already be within SCCM in order to add it to a collection, an action typically done for you by SCCM when it performs AD discovery or establishes contact with the SCCM agent on a computer. But again, we’re focusing on a VM target, and a New Computer environment without baggage, so our target should not already be in SCCM. Importing the target is the best way to create the SCCM object without having any history behind it.

The simplest import consist of identifying two pieces of information: The computer Name and MAC Address. Most VMs when spun up have a  dynamically created/assigned MAC address. Although it is completely possible to create a VM and then obtain it’s MAC address, it is easier and safer to create your own MAC address and assign it to the VM. That way, you have complete control over the SCCM computer import’s object identification and the target VM. For this example, we’ll use the MAC address “6F:5E:4D:3C:2B:1A“.

  1. From the Configuration Manager console, navigate to Assets and Compliance\Devices
  2. Right-click Devices and select to Import Computer Information
  3. Choose to Import Single Computer
  4. Specify a Computer Name (make note of it), and supply the documented MAC address.
  5. Complete the wizard.

Next, create a new Device Collection, calling it what you wish, and limiting the collection to “All Systems”. On the membership rules page, add a new rule of type “Direct Rule” and follow the wizard, keeping the Resource class as a System Resource, and using “MAC Address” as the attribute name. In the Value field, enter your documented MAC address. Pressing Next will then show you the Computer Name of the matching object, of which you will select and then complete the wizard.

Deploy The Task Sequence

With the target computer imported and identified within a collection, we can now deploy your TS.

  1. From the Configuration Manager console, navigate to Software Library\Overview\Operating Systems\Task Sequences
  2. Right-click on the B&C TS and select Deploy
    1. Select the Collection created earlier.
    2. On the Deployment Setting screen, choose to only make the deployment visible to “Only media and PXE (hidden)”.
    3. On the Scheduling screen, ensure that the assignment is scheduled for “As soon as possible”, with a rerun behavior of “Always rerun program”.
    4. Complete the wizard.

Create Task Sequence Media

Although your environment may be setup to deploy via PXE or USB, for our automation we need to kick off deployment via ISO and have that media configured for unattended OSD.

  1. From the Configuration Manager console, navigate to Software Library\Overview\Operating Systems\Task Sequences
  2. Select Create Task Sequence Media from the ribbon bar.
  3. Select “Bootable media”, and ensure that you have checked the “Allow unattended operating system deployment” option.
  4. Configure the media management as best for your environment.
  5. When configuring a Media Type, ensure you’ve selected “CD/DVD set”, then specify the location and name of the ISO. Remember where you put it as we will be moving it later on.
  6. On the Security page, ensure that you have unchecked both “Enable unknown computer support” and “Protect media with a password”.
    1. Creating a self-signed media certificate is fine, but set an expiration date for more than one year. At a target rate of once per quarter, you don’t want to find that the process breaks a year down the road because of an expired certificate, something that will be hard to track down.
  7. Complete the wizard, with the configurations needed for your build environment.

SCCM Summary

At this point, you have your zero touch B&C TS, a collection containing your target hardware, said TS deployed to that collection, and an ISO image set to boot in an unattended mode. If a member of your collection were to boot to this CD, it would automatically kick off the TS and build a reference computer.

Automating The Process

Although possible to implement automation and have it work remotely, for this demonstration environment my automation is running on my Hyper-V server. Very little manual prep work has to be done to get up and running.

  1. Copy your ISO to the Hyper-V server. Your VM will be accessing it, and having it local reduces the chance of something going wrong later as you’re not introducing an additional resource. Document where you place the ISO file.
  2. Configure PowerShell. Your automation will be a PowerShell script, which is blocked from running by default. Your server needs to have the Execution Policy configured to allow for scripts to run. From an elevated PowerShell command window, you can determine the current Execution Policy using the Get-ExecutionPolicy cmdlet, and set the Execution Policy using the Set-ExecutionPolicy cmdlet. This will need to match your security model, but for this demo, RemoteSigned will work just fine.
  3. Credentials. Your script will need to have rights on your Hyper-V server to manipulate VMs. Ensure you have a service account which will grant your automation the needed rights.

In your environment, there is no limit to what you can automate, and for the B&C task, there is no hard “end” to where your automation must stop. For the purposes of this demo however, the automation stops after the successful capture of the WIM and an environmental cleanup.

You can never add to much error trapping in your scripts. It is always better to manage what can go wrong than ignoring it and either hoping for the best or letting your automation destroy the environment. That said, this demonstration script utilizes minimal error trapping for the sake or clarity and space. You are encouraged to flesh out your version.

Design Considerations

As you’ve seen above, this demo uses a static MAC address to identify the computer object within the SCCM environment. This therefore means that you must configure your VM with the same MAC address in order to get it to work, or you must capture the MAC address of an existing VM. In a virtualized world, spinning up a VM with a configured MAC address is by far simpler than determining the dynamically assigned MAC address and/or having to constantly update SCCM when the environment changes.

Along the same “simplicity’s sake” line of thinking, it is also much easier when ensuring a completely clean and New Computer environment to spin up a new VM when needed instead of going through a cleanup or snapshot process. This demo spins up a VM when needed, and deletes it when it is done, assuring a controlled and consistent environment. This has the added benefit of ensuring that when your VM initially boots, because there is no other file system, your automation won’t be presented with the “Press any key to boot from CD or DVD….” message, derailing the entire process if not answered.

The Variable Settings

Very little is actually needed to properly spin up and configure a VM. The following bits of information we need to identify:

  • The Name of the VM
  • The Path to store the VM configuration data
  • The Path to store the VM’s VHD
  • The Path and File Name of the ISO
  • The Name of the Network Switch
  • The amount of RAM to give the VM
  • The Disk Size for the VHD

Fortunately, most of this can be dynamically discovered, and the rest hard-coded. Let’s look at the variable declaration part of our script:

01  $NetworkSwitch = (Get-VMSwitch | Where-Object { $_.SwitchType -eq "External" })[0].Name
02  $VMName = "SCCM B&C Automation"
03  $VMPath = (Get-VMHost).VirtualMachinePath
04  $VMHDD = ((Get-VMHost).VirtualHardDiskPath) + "\SCCMB&C.vhdx"
05  $VMISO = "[Path\FileName].ISO"
06  $VMRAM = 2GB
07  $VMHDDSize = 80GB
08  $VMMACAddress = "6F-5E-4D-3C-2B-1A"

Hyper-V has three Switch types, External, Internal, and Private. It can also have multiple Switches configured. Line 01 above makes a lot of assumptions, in that it is assuming you have at least one external switch configured. As your environment may differ, you can also just specify the name of the external switch to use, or even create your own. This snippet shows the creation of one if an external switch is not configured:

If ((Get-VMSwitch | Where-Object { `
   $_.SwitchType -eq "External" }).Count -eq 0) {
      New-VMSwitch -Name "SCCMB&CExtSwitch" -SwitchType External 
      $NetworkSwitch = "SCCMB&CExtSwitch"
      $bDeleteNetworkSwitch = $true
Else {
      $NetWorkSwitch = (Get-VMSwitch | Where-Object { `
         $_.SwitchType -eq "External" })[0].Name
      $bDeleteNetworkSwitch = $false

We need to know where we are going to be storing our configuration data, so Line 03 obtains the current Hyper-V’s settings for this and uses them. Line 04 is similar in that we are looking for the location of the VHD files, and specifying the name of one to create. Line 05 is where you will put in the full path and name of the SCCM ISO you created. Lines 06 and 07 are self-explanatory, but configurable for your environment. Line 08 is your MAC Address used within SCCM for the target computer object.

Create And Configure The VM

09   New-VM -Name $VMName -Path $VMPath -MemoryStartupBytes $VMRAM `
10      -NewVHDPath $VMHDD -NewVHDSizeBytes $VMHDDSize -SwitchName $NetworkSwitch `
11      -BootDevice CD
12   Set-VMDvdDrive -VMName $VMName -Path $VMISO
13   Set-VMNetworkAdapter -VMName $VMName -StaticMacAddress $VMMACAddress

Yes, that’s it. Line 09 (continuation on 10 and 11) is all the information needed to spin up a generic VM, in the location required, with the basic RAM and VHD HDD size, a NIC connected to the external switch, and (most importantly) setting the CD/DVD as the first boot device. Line 12 attaches our ISO to our VM, and Line 13 assigns our static MAC Address. We’re left with a powered off VM ready to boot to our SCCM environment, identified as our target VM thus automatically launching our B&C TS.

Launch and Monitor the VM

14   Start-VM -Name $VMName
15   While ((Get-VM -Name $VMName).State -ne "Running") { Sleep 5 }
16   While ((Get-VM -Name $VMName).State -ne "Off") { Sleep 120 }

Line 14 starts the VM, while Line 15 (which is a bit of overkill but ensures that we don’t jump the gun) waits for us to be in a running state before monitoring the progress.

As our VM is set to boot to the CD, and our CD set to allow for unattended deployment, our VM will spin up, load the WinPE environment on the ISO, connect to SCCM, identify itself via the MAC address, and as our deployment is set to run as soon as possible, the zero touch TS will start the build process. There are subsequent reboots that will happen during the build process, and even though our VM is always configured to boot first from CD, the presence of a native OS available triggers the “Press any key to boot from CD or DVD…” prompt, which will timeout and allow for the continuation of build process. After sysprep and the final capture, our VM will shutdown.

It is that state which Line 16 is lazily monitoring for, going back to sleep for 2 minutes each time it sees that the VM is powered on. Once the VM has powered off, we can continue with our automation.

Cleanup And Other Tasks

17   Remove-VM -Name $VMName -Force 
18   Remove-Item -Path $VMHDD
19   If ($bDeleteNetworkSwitch) { Remove-VMSwitch -Name $NetworkSwitch }

Line 17 deletes our VM. This ensures that we aren’t accidentally reusing it later, and saves us the effort of having to script snapshots or other cleanup activity. As the removal of a VM does not automatically remove the VHD associated with it, in Line 18 we just delete the VHD. This deletion process also returns resource back to the Hyper-V server instead of keeping them configured always for a process that runs 4 times a year.

Line 19 should only be there if you went the discovery route and created a switch if one was needed. Otherwise, if you stuck to Line 01 as-is or just hard-coded a switch name, it isn’t needed.

At this point. you’re left with your configured WIM at the network location specified in your TS. Your automation could end here with perhaps an email sent to you via the super-easy Send-MailMessage cmdlet, or continue with a move of the WIM file, and an automated update using the SCCM PowerShell cmdlets. Those choices are up to you, but our next step is to schedule our process.


Your trusty Task Scheduler is your best friend here. Create a new task, with a Monthly trigger, configured for (say) the First Monday of January, April, July and October. Configure the action to run your PowerShell Script, with security configured to run under your service account whether the user is logged in or not. Give it highest privileges.


It takes less than an hour to automate the generation of your base deployment WIM, and leaves you with reduced administrative tasks and better adherence to your desktop deployment update policy. Win-Win!


Share This Post

A senior architect with over 16 years of experience in desktop design, delivery and production management. 14 years of law firm-centric experience in developing, integrating, and implementing robust and full-featured desktop solutions, focused on solid Microsoft and Microsoft partner platforms crafted to deliver an optimal fit for the environment.

1 Comment

  1. An interesting article, but I think the main challenge and issues with attempting to fully automate the build and capture process come from having to apply 100+ software updates and having to repeat the “Apply Software Updates” step many times to accomplish this. My preference is to use the Virtual infrastructure to create my reference PC and snapshot prior to cleanup and capture – each quarter we just revert to the snapshot, re-patch (from Windows Update), re-snapshot, cleanup and capture; minutes worth of work instead of hours worth of waiting and uncertainty as to whether the image is patched fully and gets captured successfully.

Leave a Reply