This post is a follow-up or compliment to creating an image of Windows for mass-distribution (Windows 7). On that note as well, the folks over at Deployment Research have a great post on creating an updated Windows 7 master image with MDT, very helpful.
This summer, Windows 10 is upon us, and we have already begun slowly transitioning some areas to Microsoft’s ultimate operating system. Largely, the process of making an image for Windows 10 is the same that is was for Windows 7 with a few twists.
I like to build my images in a virtual machine. This approach allows me to create an image that is truly hardware-neutral. Using actual hardware could work, but there still may be remnants of that hardware that sysprep does not generalize, and could potentially make it into production. The actual hardware approach worked for Ghost, but it is not necessary anymore with MDT. Choose whatever virtualization tool out there, they all work very well, some are even free. Here’s the best of what’s around:
- VMware Workstation/Player – Not free, but feature-rich and integrates into vSphere.
- Microsoft Hyper-V – Comes with x64 server versions of Windows (2008 and later), and x64 desktop versions of Windows 8 and later. Despite all of the “server” nomenclature, client operating systems will work just fine.
- Oracle VirtualBox – Free, and available for Windows, macOS, and Linux as both the host OS and the client OS.
I am aware that there are virtualization products for macOS, and Linux, but we’re working with Windows. I think it is best to just stick with that for the whole process. I’m sure everything would be fine if Windows was not the host operating system.
Given that, you’re going to want to do this work on a moderately beefy PC. Not all of us have Dell Precision workstations, or even access to a server with Hyper-V or vSphere installed, but using an under powered PC will make building images, and just using virtualization a slow and miserable experience. The key is storage. Creating images, multiple images with snapshots, and testing uses up a great deal of space on the disk drive(s). I would not bother using a drive smaller than 1TB. It’ll work on something smaller, but in that case, you are limiting the whole process. Even 1TB SSDs are reasonably priced now. SSDs are king, but still not equal to spinning disks in price per gigabyte. A combination of something like a 256GB SSD for the host operating system and applications with a 4TB spinning HDD for storage would work well. RAM is also very important because, when using VMs, RAM is being used by both the host and guest operating systems, at the same time. Try to max-out what your PC will take. 32GB, 64GB of RAM is not unreasonable for this type of work.
Modern CPUs are plenty powerful for many tasks, virtualization too. Intel CPUs have extensions specifically for virtualization. Quad-core CPUs should be a pre-requisite for a host PC that will do virtualization. You could use a dual-core CPU, but recall the part from above about under powered PCs and virtualization. If you can get a CPU with more cores, 6, 8, great! Xeon CPUs are really nice. I wouldn’t bother with anything under a quad-core i7. Another thing to also consider, that is sometimes overlooked, is bus speed. You could have the fastest CPU with many cores, a ton of RAM, working off a sweet 2TB SSD, but if the bus that connects all of these devices together is small, all you are creating is a digital traffic jam. NVMe, and M.2 SSDs are slowly replacing SATA-based SSDs and spinning HDDs in consumer and business PCs. They offer a significant increase in throughput and speed for data storage. DDR4 memory is the latest and greatest in RAM technology, until 2020, when DDR5 is expected. It is not the cheapest, but DDR4 outperforms all of its predecessors. Obviously, you want to get the best set up you can, but I understand budgets have limits.
Virtual Machine Settings…
This can vary from place to place, but I would use at least 4GB of RAM, one vCPU with 2 cores, and a 128GB VHD. That has worked well for me with Windows 7 and 10. If you can give the VM 8GB of RAM, do it. The smallest disk drive we have out there is a 128GB SSD in some Dell OptiPlex 9020s we purchased in 2014. When finished, my image has a disk footprint of around 70GB (35GB compressed by dism). If the new image will be small, then a 64GB VHD is fine. That is as small as I would go. It is possible to squeeze an image of Windows 10 (plus updates), Office 2016, Adobe Reader, Chrome, VLC, and AV software onto a 32GB drive, it is a tight squeeze. Windows grows in size over time, and 32GB will be gone long before you even realize it. I’m starting to think 32GB is too small for an iPhone… The virtual NIC should be configured for NAT, and not bridged to the production network. We’ll have a fresh install of Windows, straight from the ISO, and temporarily unpatched. The image should not see the production LAN until it is ready for testing (patched), or ready for use.
After the guest VM is created for the new image, connect its virtual CD/DVD-ROM drive to the ISO file for Windows 10. In VMware Workstation, new VMs, with no OS installed, automatically boot to the virtual CD/DVD-ROM by default.
Follow the on-screen prompts to install Windows into the VM, but STOP after the first reboot from install/file copy to OEM/Windows setup. Setup will stop at that point, and wait for user input. There, we’ll use audit mode to finish setting Windows up the way we would like it. I have more information about installing Windows 10 in a separate post.
To get into audit mode, press control + shift + F3 all at the same time, like the three-finger salute (control + alt + delete). Windows will reboot, and automatically log in as the built-in administrator account, and will continue to do so, no matter how many times you reboot, until sysprep is run. Here, we’ll customize Windows 10 as desired, then run sysprep with an unattend.xml file that copies our profile over to the default (CopyProfile).
From within your virtual machine software, take a snapshot of the VM, at this point.
Most corporate or “work” PCs have Microsoft Office installed along with Windows and other common programs. Microsoft/Windows Update is used to update both Office and Windows. At this point, I install Office (silently with a MSP file), and enable Windows to update other products in addition to itself. This is done from the new Settings application \ “Updates & Security” \ “Advanced options” \ “Give me updates for other Microsoft products when I update Windows.”
Once that is set, run updates on the new VM until there are no more left. The later the build of Windows 10, the fewer updates will be required. Microsoft Office 2016 has been available for some time, and has a decent amount of available updates online. Once the updates are finished, shut down the VM, and take another snapshot.
Some basic applications, which are not included with a regular install of Windows, are utilities that other applications use. Applications like the various Visual C++ Redistributables (VCPP), Microsoft Silverlight, and Updated .NET Frameworks (4.5/4.6). These are easily found online, and can be installed silently. The Deployment Research site has a script that gathers all of the C++ Redistributables together, and installs them, silently, in one script.
Download the VCPPs from the Microsoft website (both x86 and x64), and move them to a folder structure named as follows: (#### = the date for the VCPP application, 2005-2015)
Source \ VC#### \ vcredist_x64.EXE
The script to install all of these can be found here.
Silverlight is also freely available from Microsoft’s website.
Next, is to install all of the regular applications that people use every day. Web browsers like Google Chrome, or Mozilla Firefox, PDF readers like Adobe Reader, or SumatraPDF, communications application such as Skype or Zoom, and multimedia apps like VLC, or iTunes. I download, and store the applications I intend to use on a server share, then use silent install scripts to install them on Windows 10, which is still in audit mode.
Some basic silent install commands for common applications. If you’re in for more details, check out ITNinja.com. They have a compendium of unattended and deployment-related information for many applications.
- Adobe Reader: msiexec /qb /i AcroRead.msi TRANSFORMS=AdobeReaderDC.mst
- Google Chrome Enterprise: msiexec /qn /norestart /i “GoogleChromeStandaloneEnterprise.msi”
- Mozilla Firefox: FirefoxSetup.exe -ms
- VLC: vlc-2.2.1-win32.exe /L=1033 /S /NCRC
- Java (if you must): jre-8u66-windows-x64.exe” /s JAVAUPDATE=0 AUTOUPDATECHECK=0
- Notepad++: npp.6.8.7.Installer.exe /S
- 7-Zip: msiexec /q /I 7z920-x64.msi
Ninite.com has a site that will create a wrapper as an executable that will download whatever freeware is chosen and install them. All in one go.
Keep in mind that the fewer applications that are placed into the image, the longer that image will stay relevant. MDT/SCCM can deploy applications in addition to the OS itself. Products like Adobe Flash Player, and Adobe AIR change so often that I just install them when the image is deployed.
Run each of the newly-installed applications and configure them as desired. Shut down, take a snapshot, then reboot and let Windows 10 continue in audit mode.
To save time and effort in configuring Windows the way I need it, I try to automate as much as possible. Scripting the basics and eliminating the redundant and repetitive tasks can save a lot of time and prevent unnecessary mistakes.
Creating user accounts – I typically make a local user account for administrative use and for general use in case the domain is somehow unavailable.
First, I create a local folder to contain log files and other goodies, then hide it. “C:\Stuff” in this example.
attrib +h C:\Stuff
echo Creating local user accounts
net user pcadmin * /add /comment:”Local admin account” /passwordchg:NO
wmic useraccount where “name=’pcadmin'” set passwordexpires=FALSE
net localgroup “Administrators” pcadmin /add
net user pcuser * /add /comment:”Local user account” /passwordchg:NO
wmic useraccount where “name=’pcuser'” set passwordexpires=FALSE
net localgroup “Guests” pcuser /add
echo Local user accounts created on %date% at %time%>>C:\Stuff\Windows-10-Config-Script.txt
The asterisk (*) after the username will prompt for the new user’s password instead of coding it into the script and leaving it for prying eyes. The last command (echo…) will create a text file and add the text between echo and the first >. The double >> will just add the text to an existing file should that be the case.
To keep from surprising users with new builds or versions of Windows 10 through Microsoft Windows Update, I set a registry key to disables Windows upgrades through updates.
reg add “HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate” /v DisableOSUpgrade /t REG_DWORD /d 1 /f
echo Windows 10 version upgrade disabled on %date% %time%>>C:\Stuff\Windows-10-Config-Script.txt
The next thing I want up and running right off of the bat is remote desktop.
echo Enabling RDP with SASC alternate port
reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server” /v fDenyTSConnections /t REG_DWORD /d 0 /f
reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp” /v “PortNumber” /t REG_DWORD /d “0xdesired_port_number_in_hex” /f
netsh advfirewall firewall add rule name=”Alternate RDP Port” dir=in action=allow protocol=TCP localport=desiredportnumberinbase10
echo RDP enabled with SASC alternate port on %date% at %time%>>C:\Stuff\Windows-10-Config-Script.txt
A facet of Windows’ default configuration is to hide file extensions. I can guess the designers at Microsoft figured doing so might be helpful to end users, but in practice I have found it to be anything but for most people. I inject a quick registry change to show those pesky extensions .
bios.bootdelay = 20000
Do you purchase computers with an OS already installed or OS-less computers?
Our PCs come from the OEMs with Windows 10 Pro, and formerly Windows 7 Professional preinstalled. We re-image all new machines with Windows 10 Enterprise from our volume license agreement w/Microsoft.
Can the built-in administrator profile that we are using in the audit mode be the copy profile we are copying from? or do we have to login as a different use and copy from that one?
It can and it should be. Builtin\Administrator should be the only profile on Windows when sysprep executes CopyProfile. Multiple profiles will result in CopyProfile not running at all, or using the wrong profile for the default.
Thanks for posting this. This VM capture process to support Cloned VMs gets a bit confusing. I am accustomed to an old way which utilized NetApp Rapid Deployment. We would just work off of VM Templates. Your article was the easiest one to follow that I have found to date on the “interwebs”. Thanks so much for the share.
Quick question for you, Jason. Can’t you just utilize MDT to run the SysPrep, but not Capture. This would generalize the VM and render is ready to Clone with VMWare (or whatever flavor of Hypervisor you prefer)?
I ran into issues installing updates (Cumulative/Feature) for Windows 10 1709 and 1803. Apparently, you cannot install Windows 10 in Audit Mode and some of these updates react in a way that the systems thinks that Windows 10 is being installed. The updates failed with a couple of different error messages:
You’re not up to date!
Your device is missing important security and quality fixes.
I actually received a popup box that stated I could not install Windows while in Audit Mode.
I’m going to forgo the Windows Updates for now and see how the rest of the article process goes but thought you might like to know and possibly comment on if you’ve had this issue.
I haven’t tried audit mode in a while, and with later builds of Windows 10. I’ve been sticking with 1607 for the time being. This is not a suggested practice from Microsoft, but I stay within their support parameters.
Yes. You can just run sysprep with a nMDT task sequence. That’s one of the available options in a new task sequence.
Thanks! I’m glad you liked it.
Starting with Windows 8.1, in the auditing mode, you cannot install updates using the Windows Update Center in Settings panel.
The Windows Update Center checks to see if the system has completed the OOBE stage (from which you are logged in). If not, the update is not performed.
To automatically update the system from the console, you can take on a very handy PowerShell module — the PSWindowsUpdate Module from TechNet.
Save the PSWindowsUpdate.zip archive to a USB drive and (this is important!) right click on it -> Properties -> Unlock.
Create file PSWindowsUpdate.cmd on the USB drive with one command:
PowerShell -ExecutionPolicy RemoteSigned -Command Import-Module PSWindowsUpdate; Get-WUInstall -AcceptAll -IgnoreReboot
Unpack the PSWindowsUpdate.zip to the folder: C:\Windows\System32\WindowsPowerShell\v1.0\Modules.
Run PSWindowsUpdate.cmd as administrator.
That’s all! Available updates will be downloaded and installed automatically.
When the update is complete, you can delete the module that was previously copied to the Windows folder.
“Hello! Would you mind if I share your blog with my
myspace group? There’s a lot of people that I think would really appreciate your content.
Please let me know. Many thanks”
I was wondering if you can run WDT and a computer that is not joined to a domain and still utilize the share \\mdtserver.company.com\deploymentshare\Scripts\LightTouch.vbs ? In other words, can I connect from the computer I want to image by using \\hostname(MDT Server)\deploymentshare\scirpts\lighttouch.vbs?
Yes. When I build an image through MDT, the install of Windows 10 I intend to capture is never joined to a domain. Sysprep will not run on a domain-joined computer. You will have to provide domain credentials to access the deployment share. The same would apply if the opposite were true. If the MDT server and its deployment share(s) were not a part of the production domain, imaging w/domain join can still be performed. You just need to have the account details correct.
Annoyingly CopyProfile is now deprecated
Very annoying. Time to start configuring the default user profile with a GPO.
Thanks for writing this article.
You’re welcome. Thanks for reading it.
Hey, thanks for the article. It’s made my experience creating a Win10 golden image much easier. I do have a question though, regarding running scripts that “debloat” win10. Should these be run through the task sequence on MDT or ran through the custom default profile on the win10 VM? Thanks!
I would run the debloat scripts during the MDT task sequence which deploys Windows. I think doing so in the image master VM would only see their return after sysprep and capture has been run. This has been my experience.
Gotcha, that makes sense. I’d also like to know if the unattend.xml file created for copyprofile should have any other settings in place? I created it and included some settings to auto configure keyboard layout, timezone, oobe skip, etc. After doing so, running sysprep, and restarting the VM, I could not find the option to login to the builtin\adminstrator account. Even after creating a new local account and signing out. I’m wondering if the answer file needs to be completely vanilla besides the CopyProfile option.
That unattend.xml file can be used to configure oodles of settings. I used to use it to specify a default set of taskbar icons for all users in addition to placing a group of input language options in the taskbar as well. The taskbar icons can now be specified in an XML file, which is used to configure the default Start menu layout for all users. Just do your research and don’t set anything in the unattend file for which you don’t know the purpose.
Hello, I tried following this guide but the page where you select Custom or Express settings never comes up during Windows 10 install; am I missing something? What version of Windows 10 has this page during setup?
That screen comes up in every install of Windows from a source where the install files and process has not been modified. An ISO obtained from Microsoft’s website, or from an OEM would include this. Install ISOs which use an unattended install file can be made to skip this screen. Is there a file called autounattend.xml on your install media?
Hey, I’d like to chime, as I was confused with this issue as well. At least in version 1809 of win10, this settings selection page does not appear. What has replaced it is a page asking for your region selection. This is where you should hold down ctrl+shift+f3 to access audit mode.
If following this guide with building an image with Vmware should we even be creating an autounattend answer file and sysprepping before we capture the image? or should we just be editing the autoauttend answer file in the DeploymentWorkbench task sequence for Capture or Deploy image? I hope i explained that ok it sounded better in my head.
Before i was editing the Autounattend file and sysprepping in the VMware image. But then i noticed that when using Deployment Workbench to capture and deploy the image that Autounattend answer file that DeploymentWorkbench has overwrites everything.
This is an 1809 install from our MSFT ISO. The settings screens are there.
The use of an autounattend answer file is optional at this point. You could use it to do a silent install of Windows, but that would skip audit mode entirely. Manual install w/audit mode would require sysprep to be run twice. Once to get it out of audit mode and again during the sysprep and capture MDT task sequence. I’ve never been able to take Windows out from audit mode with the syprep and capture process.
i guess i am just getting thrown but all the unattend.xml files. If i follow the guide and run sysprep generalize in the vmware with an autounattend.xml file. But then there is an unattend.xml if the MDT capture task and the another unattend.xml in the Deploy image task.
The main reason for sysprepping with an unattend file in the first case is to copy over a customized user profile to the default user profile. This is not required, not even suggested any more. MDT’s sysprep and capture task sequence also uses an unattend.xml file to perform every step needed by that task sequence.
thanks for the info. So, in the Capture Image Task and the Deploy Image Task which unattend.xml file takes precedent. Do i need to have the same settings in both so that my image gets deployed exactly how i had it when creating it in the VMWARE environment?
The tasks used to capture an image with MDT is usually different that a task to deploy an image. By default, MDT will ask if an image of a deployed install should be captured, but that isn’t usually an appropriate option.
Anyway to do a zero touch deployment when there is a OEM OOBE Win 10? With no OS, I can just plug it into a port.
Are you trying to redeploy the OS that came with your computer? Zero touch is possible with MDT but it requires the use of a database, PXE server and substantial modification.
Your blog is awesome!! good job man!!
I create a master image in audit mode. Sysprep with my custom unattend and then capture it into wds.
I then have an unattend for the wds server which wipes drive and sets locale, etc. I also attach the same unattend I used to sysprep to the wim I’m deploying.
This allows a complete hands off install once PC’s are in network boot. You can even set the wds unattend to join the domain.
This is a good article and has many excellent steps. Thanks