I build a LOT of App-V Sequencer and Client VMs over the course of a year. Not only do I test each release, but hotfixes and a bunch of private builds that I get, and then I also need to handle changes to my own tools (which need testing before release). Plus I want to reuse the technique to build VMs for all of those training classes. So it should be no surprise that I automate that process as much as I can.
My choice of tool? Microsoft Deployment Toolkit (MDT).
ISO–>Task Sequence –> Application
The output of MDT is a bootable ISO that can be used for a fully or semi-automated installation. Within an ISO, you can have one or more Task Sequences.
Like in other tools, the Task Sequence is an ordered set of instructions that does the installation and configuration activities. The task sequence uses a number of prebuilt sets that cover the basic activities that you need, such as installing the OS itself, or joining a domain. I use one that could be used to install or upgrade a users PC and then just disable stuff I don’t need, like the upgrade activities. To install and /or configure software in the built OS, you add additional installers or scripts into the Task Sequence. These are called “applications” in MDT, and since they are separate from the Task Sequence themselves, you can create them once and use them in all the Task Sequences that need them.
The applications can be anything that you can run; msi, exe, and scripts. You can have the “application” fully automated or prompt for input if you like (I keep them fully automated).
When a new version of an app comes out, I just make a copy the old “application” in MDT pointing to the new installer, and then change the task sequence to use this new copy. And then I rebuild.
When I build, I create 12 different kinds of test systems. These are all desktop systems; I don’t rebuild RDS systems very often (I have a separate base RDS ISO and manually install for that) . Once I build the framework for what I wanted in MDT, the build process is fairly simple. It runs in three phases.
Phase I: Defining the ISOs
There are 12 task sequences. 6 are x86 and 6 are x64. In each case:
- Windows 7Sp1 Sequencer
- Windows 7SP1 Client
- Windows 8 Sp1 Sequencer
- Windows 8 SP1 Client
- Windows 71 prepped for Sequencer but without Sequencer
- Windows 71 prepped for Client but without Client
I use the ISO/Task Sequence to build a sysprepped template image VM disk. Ultimately, I want something that acts a little like non-persistent VDI so I get a completely clean OS when I want it, but that I can use like a persistent VDI for a couple of days when I want, rebooting or even take snapshots.
When I need to rebuild, it is the task sequences that get modified, generally substituting one app version for another. Each installer is run from a script file kept in the same folder with everything needed for a silent installation with any additional parameters set. Quite often, I find that I can add a /norestart option to get rid of reboot request warnings. After determining which ones are independent from each other, I can order several installers together and reduce the number of reboots.
Each Task Sequence is fairly similar. So what is in my general Sequencer Template Build Task Sequence?
- Prep Disk (VHD)
- Disable BitLocker
- OS using an adjusted unattend.xml to perform a full silent install of the OS. Adjustments include:
- Setting Language and Time zone
- Setting Local Admin Account and Password
- Automatic naming (non domain joined since it will get Sysprepped)
- Get rid of IE OOF stuff
- Set IE Homepage
- App-V 5 Prerequisites (some not needed on Windows 8)
- Dot Net 4.5.2 (needed for App-V 5 SP3, otherwise 4.0)
- KB2533623 (or newer, appropriate for bitness and OS Version)
- WMF 30 (appropriate for bitness and OS version)
- Silverlight 5.1 (client only)
- Reboot
- App-V 5 Sequencer
- Disable Services for Sequencer (Defender, Search, Update)
- Sequencer Install
- Set Execution Policy for PowerShell to Remote Signed
- Copy Sequencer Shortcut to desktop
- Copy PowerShell Shortcut to Desktop (OS Specific)
- Reboot
- Non App helpful tools
- BGInfo
- Procmon
- Process Explorer
- Disable Network Logon Password Change
- Enable Remote Desktop
- Install Hyper-V Integration Components (Win 71 only)
- Reboot
- Registers a first boot script.
- Optimize: Ngen Recompile
- Optimize: Win7OS (modified from script from MSfor VDI)
- Reboot
- Prep-ReadyBoot (sleep 200 seconds; reboot>>Repeat 5 times)
- SysPrep
The client build is similar, but I add:
- Latest AppV Client Hotfix
- AppV_Manage
- ACE (for editing DynamicConfiguration files)
An option to the above for those that want to keep VC Runtimes out of their packages is to install All of the VC Runtimes into the template. This would be done in reverse order on the sequencer, and forward order on the client. This would probably be done prior to adding the Client/Sequencer.
I build the 12 MDT ISOs by updating the media for each. Once the task sequences are adjusted for the altered application version, clicking 12 times to update the ISO image is the hardest part of the remaining process. I originally had one humungous ISO with all of the task sequences, but it became too unwieldy (and required a manual bitness selection for the bootrom in Phase 2).
Phase 2: Building the 12 templates
After the 12 template ISOs are built, I use these to build 12 template VHDs, which will be used as linked clones.
The build of these 12 templates is scripted using a single PowerShell script that for each:
- Shuts down the current template VM, if running
- Deletes the current template VM, if present
- Creates the new template VM and VHD, mounts the Appropriate MDT ISO. It removes all network adapters to prevent Windows Updates.
- Boots the VM, which is fully automated. I have it not shut down at the end just so I can review the report to be sure it built clean. I close the report and shut down the OS.
Phase 3: Building the actual VMs
Phase 3 is about building the actual VMs as the Hyper-V equivalent of “linked clones”.
For Phase 3, I have another cmd file that calls another PowerShell script, supplying the count of each type of VM that I want built. The clients have a standard naming by type that ends with the number (1-9) as the last character.
The PowerShell script that will build as many VMs as I need from each templates type. For each it VM to be created, it:
- Shuts down the current template VM, if running
- Deletes the current template VM, if present
- Creates the new template VM and VHD. This time the VHD is a differencing disk tied to the template (Microsoft’s version of linked clones). It them mounts the Appropriate MDT ISO, adds in the network adapters with a programmed MAC address (which is used to trigger DHCP to get ordered IP addresses).
- Injects an updated unattend.xml to the VHD containing the machine name and domain join information, plus another first boot script.
- Starts the VM, which finalizes the OS into the domain and OU, and runs the first boot script to complete remote desktop access and remove unattend files that contain the domain admin password to join the domain. You don’t forget about those ones when you build VMs, do you?
Since I control Group Policy in my lab, I also set a few things via GPO, one for clients and one for sequencers. Each VM has a name that matches the OS name and indicates the purpose, OS, bitness, plus the instance number. It is in the domain in OUs separated for sequencers and clients. They have with Remote Desktop Connections enabled for all domain users. Each gets a pre-known IP address thanks to DHCP and automated MAC Address assignments.
I shut down each OS and take a snapshot.
Other Uses
The great thing is that I can use this to build multiple machines from the templates for training classes. I avoid the need for a VDI broker by using a tool I wrote called “ClassAct” that controls groups of VMs (input via an XML file) that allows me to revert all of the sequencers in one shot as we move from lab to lab. (It uses the Hyper-V PowerShell APIs). Students can RDP into the lab via name or IP address (if they don’t want to take my DNS) by knowing their assigned number.
So why don’t I use SCVMM here somewhere? I think it’s just too complicated to bother setting up. This works for me.