VM MASS DEPLOYMENT with Powershell – Hyper-V

As you already know powershell is really useful in several scenarios where you need to automate task operations in windows world. I personally use “Powershell for Hyper-V” often (http://pshyperv.codeplex.com) especially in mass deployment scenarios where I need to deploy hundreds of virtual machines.

In this blog post I will use the powershell commandlet “NEW-VM” which I had used to create a loop within a script.

The goal here is to deploy, 384 VMs in a automated way 🙂

Therefore I had created an MASTER-VM, which I had installed with all the required application (AV, Apps, Updates.…), tools and finally sysprepped the VM. The exactly command to generalize the VM –> SYSPREP /OOBE /GENERALIZE /SHUTDOWN  .

required preparations:

1. Download and Install Powershell Library from codeplex –> http://pshyperv.codeplex.com
2. Customize General Parameters in Script like
    - Number of required VMs (a.e. start at 1 and run 384 loops = 384 Vms)
    - Prefix name for your VMs (a.e. W2K8R2-T)
    - customize vRAM and vCPU settings
    - change destination drive where VMs should be created ("V:\"+$vmname)
    - copy your MASTER-VM (sysprepped) and amend location where MASTER-VHD can be found a.e. V:\Master\MASTER_R2.vhd
    - amend disk drive at "ADD-VMDISK" operation a.e. Add-VMDisk $vmname 0 0 ("V:\"+$vmname+"\"+$vmname+".vhd")Here we go with our powershell script:

Import-Module hyperv
# Here we import the hyper-v specific hyper-v module which must be downloaded and installed 1st

For ($Counter=1; $Counter -le 384; $Counter++) {
# most important section within this script. Here we define our loop and also how much VMs we want to create here. In my case the loop will start at 1 and run 384 times

# Here we give our VMs an prefix for name which is called in my case "W2K8R2-T" +  counter number = a.e. W2K8R2-T1

# Default VM RAM setting = 1 GB RAM

# Default vCPU setting = 1 vCPU

New-VM -name $vmname -Path ("V:\"+$vmname)
# Now here we call the powershell commandlet "NEW-VM" and point to my drive V:\ where the VMs should be created

Copy V:\Master\MASTER_R2.vhd ("V:\"+$vmname+"\"+$vmname+".vhd")
# here we duplicate (copy) the master-VHD to the destination drive (source -> destination)

Set-VM -vm $vmname -bootOrder @(2,1,0,3)
Set-VMMemory -vm $vmname -memory $vmram
Set-VMCPUCount -vm $vmname $vmcpu
Add-VMNIC $vmname
Set-VMNICSwitch -vm $vmname -nic (choose-vmNic $vmname) (choose-VMswitch 0)
Add-VMDrive $vmname 0 0
Add-VMDisk $vmname 0 0 ("V:\"+$vmname+"\"+$vmname+".vhd")
# add disk which we had copied earlier to the VMs configuration

Add-VMDrive $vmname 1 0 -DVD
Start-VM $vmname
sleep 30

Now we can go and take us a loonnng break 😉 as the copy time of the MASTER-VHD (depends on size of MASTER.VHD) does take the most of the runtime of the script. My recommendation here would be to use dynamic disks but of course this depends on the performance requirements of disk I/O for these VMs.

PS: Of course there is room for improvements but this blog/script should “only” give you an idea how the powershell library can be used and with your own creativity there is really no borders for creating a customer friendly solution 🙂

If you have any further questions please let me know.



Comments (7)
  1. thank you for sharing with us, I think this website really stands out : D.

  2. Ryan says:

    This is a great post. The only problem I’m having is that all the Windows XP machines I clone have the same name. Is there a way to name each XP machine to match the name of the VHD or whatever you specified as the name in the script?

    1. Yes, you need to mount your VHD each time and copy an sysprep unattended file into c: root folder which will be then used for automated configuration of each machine 😉

      Hope that helps.

      1. I realize this thread is long dead, however – what’s the best way to mount the VHD/do the copy for each machine?

  3. Paul Coe says:

    Great Script. Thanks!!

    Is there a way to select which switch the NIC is connected to? I have two to select from and I’m being prompted when I run the script.

    I assume the section ‘choose-VMswitch 0’ is supposed to do this for me, but I’m stilling being prompted.

    I don’t know what ‘choose-VMswitch’ is as I can’t find any info out about it. The PSHyperV manual has a slightly different looking format for ‘set-VMNICSwitch’.

    I am hoping I could change the current line in the script:
    Set-VMNICSwitch -vm $vmname -nic (choose-vmNic $vmname) (choose-VMswitch 0)

    Any ideas?


  4. Paul Coe says:

    Ah ha!

    I found that I could change the AddVMNIC line to include the VIrtual Switch that it should be connected to. So, I added a 2nd NIC that I also require and commented out the Set-VMNICSwitch line.

    Add-VMNIC $vmname -virtualswitch “External Virtual Network”
    Add-VMNIC $vmname -virtualswitch “Internal Virtual Network”
    # Set-VMNICSwitch -vm $vmname -nic (choose-vmNic $vmname) (choose-VMswitch 0)

    All sorted 🙂


Comments are closed.

Skip to main content