Using DeployImage and Windows PowerShell to Build a Nano Server: Part 4

Summary: Use the new cmdlets in the DeployImage module to simplify the deployment of a Nano Server.

Honorary Scripting Guy, Sean Kearney, is here to get into the really fun part of deploying a Nano Server—the actual deployment part.

   Note   This is a five-part series that includes the following posts:

Yesterday, I showed you the New-UnattendXMLContent cmdlet to help you name the Nano Server and provide direct settings, such as the time zone. Today we’re going to look at creating partitions and applying the image—our actual process.

If you were to try to apply Nano Server to a VHD file, it’s actually very easy in Windows 10. You can natively create the VHD, mount it, and then access it directly as if it were a physical disk. Following is a simple example of creating a new VHD file, mounting it, and then assigning it to a disk object in PowerShell. Our example is called Sample.VHD and is a 20 gigabyte dynamic disk in the C:\FOO folder:

New-VHD C:\FOO\sample.vhd -SizeBytes 20gb –Dynamic

Mount-VHD C:\FOO\sample.vhd

$Disk=Get-Disk C:\FOO\sample.vhd

If this was a physical disk inside a computer (not a VHD), I would normally use the Get-Disk cmdlet and filter on the type of SCSI, SATA, or SAS. But DeployImage has a cmdlet with that wrapped into it. We can grab all internal disks in the following manner:


It’s simply a wrapper around Get-Disk | Where-Object { $_.BusType }, but I find it a little nicer to use.

For a physical disk on a target server (if there is only one), we can use this:


Next we need to partition the disk. For this, I’ve set up a small cmdlet to deal with the two most common partition setups for WIM files: basic MBR and GPT.

You can create your own custom script for this, but if you’d like to easily create a GPT partition on a physical disk, you can use the New-PartitionStructure cmdlet. It has three mandatory parameters for a physical disk: the disk object, the operating system drive letter, and the boot drive letter.

This cmdlet will clear the old partition structure, create a new one, format the needed drives, and assign the drive letters. Here is an example on a physical disk with the new boot drive being assigned drive letter G and the operating system drive being assigned drive letter H:



New-PartitionStructure -Disk $disk -BootDrive $Bootdrive -OSDrive $OSDrive

We can use the same structure on a virtual disk, but we can also lay out a simple MBR structure. This will be part of the simple process of converting a WIM to a VHD. In this case, both the boot drive and the operating system share the same drive.

New-PartitionStructure -Disk $disk –MBR -BootDrive $Bootdrive -OSDrive $OSDrive

Now that we have a partition structure, we can use the Expand-WindowsImage cmdlet on the operating system drive letter.

Remember that custom Nano Server WIM file we created on Tuesday? Grab the location provided (it was defaulting to ‘C:\Nanotemp\Nanocustom.wim’):


Expand-WindowsImage –imagepath “$wimfile” –index 1 –ApplyPath “$OSDrive`:\”

Now that we have an image on a disk, we can build out our Unattend file content to automatically name the system and join it to the Contoso domain (remember yesterday’s example):

$Content= New-UnattendXMLContent –computername ‘TESTNano’ –joindomain –Domainname ‘Contoso’ –Domainaccount ‘JoinAccount’ –DomainPassword ‘P@ssw0rd’ –DomainOU ‘CN=Ourusers,DC=Contoso,DC=local’

Add-Content C:\Foo\Unattend.xml –value $content

Copy-item C:\Foo\Unattend.xml –destination “$OSDrive`:\Windows\system32\Sysprep\unattend.xml” –force

We are actually almost done—except for two key pieces. We need drivers for the target computer (we need to see that hard disk and network card), and we need to apply boot code.

The cmdlet for adding drivers is nice and simple—you need to provide the source folder for your drivers and the destination for the Windows folder. The beautiful part is that the cmdlet will recurse through the folder structure and grab all the drivers from there.


Add-WindowsDriver -Driver $DriverPath -Recurse -Path “$OSDrive`:\” -ErrorAction SilentlyContinue

Now there is only one additional piece—making the system bootable. There are two commands in Windows for making a disk bootable: BCDBoot and Bootsect. For most cases, we can use BCDBoot.

To make this process more seamless, BCDBoot and Bootsect have been wrapped into a cmdlet called Send-Bootcode, which only needs the drive letter for the boot drive and the operating system drive.

Send-Bootcode –bootdrive $Bootdrive –osdrive $OSdrive –bootdrive $Bootdrive

…and we’re done. Yep. You’ve just deployed a Nano Server. If you use a VHD as the target and create the MBR partition with the same code, you’ve converted a WIM to a VHD.

Within the DeployImage structure is a script called DeployNanoServerPhysical.ps1, which is a simple example of this post in action.

Come back tomorrow for our final day of this series. I’ll combine last week’s work of a bootable Windows PE image with PowerShell and this week’s work. I’ll show you how to automatically build out deployment media.

I invite you to follow the Scripting Guys on Twitter and Facebook. If you have any questions, send email to them at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, always remember that with great PowerShell comes great responsibility.

Sean Kearney, Honorary Scripting Guy, Cloud and Datacenter Management MVP 

Comments (5)

  1. BeeLove says:

    Now you lost me. The TechNet instructions seem so much cleaner.

  2. @BeeLove

    The difference in the process is what presently is not covered in the TechNet Instructions which is getting drivers injected into the image and applying the file structure directly to a standard GPT partition.

    The end result of this process (when done) is a USB Key that can almost fully automate the Deployment of Nano Server or almost any other WIM file

    The TechNet gets you to the VHD part and gives manual instructions on using BCDEDIT, but this solution should end up giving you a module you can port onto a Windows PE key with Powershell to do almost any task you’ll need in deploying a WIM file with just PowerShell

    It’s just another option that does not necessarily negate the TechNet solution; just a different way of looking at it


  3. Tim says:

    You use the command "$Disk=Get-Disk C:FOOsample.vhd" in your above instructions. But, to get a specific disk, do you not need to reference it by number and not path? I try your command and get an error – "Cannot process argument transformation on parameter
    ‘Number’. Cannot convert value "C:FOOsample.vhd" to type "System.UInt32[]".
    First issue Get-Disk with no parameters to get a list of all the disks mounted. Then use the command "$Disk=Get-Disk n" where ‘n’ is the number of the mounted VHD file.

  4. Explode-WindowsImage says:

    I was typing Explode-WindowsImage apparently that is the wrong command but I typed it 3 times…lol

  5. @Tim

    The one line is most definitely a typo. It should actually be reading

    Mount-Vhd C:FooSample.vhd
    $Disk=Get-VHD C:FooSample.vhd | Get-Disk

    With this is will correct grab a VHD as a Disk Object


Skip to main content