Weekend Scripter: Use PowerShell to Build Multiple Virtual Machines

Weekend Scripter: Use PowerShell to Build Multiple Virtual Machines

  • Comments 3
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to build multiple virtual machines with Hyper-V.

Microsoft Scripting Guy, Ed Wilson, is here. One of the really cool things that I love about Windows 8 is having real-live, honest-to-goodness, Hyper-V built in to the operating system. And of course, that means also having the Windows PowerShell cmdlets to manage it. With the power of modern laptops (the Scripting Wife has 32 GB of RAM, a solid-state drive, and a SATA 3 drive on her new laptop), running multiple virtual machines is a real option—and a real treat.

The other day, I needed to create three virtual machines to test my instructor-led lab scenario that I am creating for TechEd in New Orleans and Madrid. Because I am in the process of redoing my network, I do not have access to any advanced deployment tools. It’s just me, my laptop, and Windows PowerShell. Because my objective is to build three virtual machines (not to write the perfect script), I decided to knock out a quick script. The result is shown here:

$name = "Client1","Server1","Server2"

$name |

Foreach {

    new-vm $_ -MemoryStartupBytes 512MB -SwitchName InternalSwitch `

    -BootDevice cd -NewVHDPath "F:\VM\$_\Virtual Hard Disks\$_.vhdx" `

    -NewVHDSizeBytes 127GB }

 

Foreach($n in $name)

{

 if($n -match 'client')

    {

     Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 4096MB -StartupBytes 2048MB -Buffer 20

     Set-VMDvdDrive -VMName $n -Path $((Get-Item F:\winsource\*client*).fullname)

    }

 if($n -match 'server')

  {

   Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 2048MB -StartupBytes 1024MB -Buffer 20

   Set-VMDvdDrive -VMName $n -Path $((Get-Item F:\winsource\*server*).fullname)

  }

}

 

Get-VM $name | Start-VM

Three important cmdlets

Because I only needed to create three virtual machines, I hard coded the machine names into a variable. I also thought it was a good idea to use easy-to-remember names. This part of the code is no surprise:

$name = "Client1","Server1","Server2"

New-VM

Now I come to the first important cmdlet: New-VM. The New-VM cmdlet creates a new virtual machine. The basic configuration for all three virtual machines is the same. I specify the startup memory, the name of the switch, the boot device, the path to the VHD, and the size of the VHD. I pipe the three computer names to the New-VM cmdlet, and I end up with three new virtual machines. This portion of the code is shown here:

$name |

Foreach {

    new-vm $_ -MemoryStartupBytes 512MB -SwitchName InternalSwitch `

    -BootDevice cd -NewVHDPath "F:\VM\$_\Virtual Hard Disks\$_.vhdx" `

    -NewVHDSizeBytes 127GB }

Set-VMMemory and Set-VMDvdDrive

Now I need to walk through the computer names by using the ForEach command. For each of the computer names, I will set the virtual machine memory and the DVD drive information. But because I will have different memory and different DVD info depending on if the operating system is a client or a server, I use the If statement.

To set the memory, I use the Set-VMMemory cmdlet, and I specify that I want to use dynamic memory in addition to the minimum and maximum bytes. I also set the startup memory. Next, I set the DVD drive to point to the ISO of the operating system I want to use.

This portion of the code is shown here:

Foreach($n in $name)

{

 if($n -match 'client')

    {

     Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 4096MB -StartupBytes 2048MB -Buffer 20

     Set-VMDvdDrive -VMName $n -Path $((Get-Item F:\winblue\*client*).fullname)

    }

 if($n -match 'server')

  {

   Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 2048MB -StartupBytes 1024MB -Buffer 20

   Set-VMDvdDrive -VMName $n -Path $((Get-Item F:\winblue\*server*).fullname)

  }

Start me up

The last thing to do is to start the newly created virtual machines. To do this, I use the Get-VM cmdlet and supply the three computer names that are stored in the $Name variable. I pipe the results to the Start-VM cmdlet. Now, I still have to walk through the wizard, but that actually goes pretty quickly on modern operating systems.

Join me tomorrow because I have an awesome guest blog about WSUS by Honorary Scripting Guy, Boe Prox. You don’t want to miss it—the post absolutely rocks!

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Please help this Probie, I see where  the code boots a new cd, but where does the VM & system get any data if

    their is no real data to load??, OR Operating system, I am still a whole BIT confused, I have copied the Script to see if

    I can get these machines to RUN< thanks for all the Scripts>

  • @Robert

    Look at the command. Use help an read how it works.

    It is recommended that you build at least on VM from the GUI before attempting to understand how to automate the process.

    A simple answer is this:

    -NewVHDPath "F:\VM\$_\Virtual Hard Disks\$_.vhdx"  -NewVHDSizeBytes 127GB }

    When you say data.  realize that VM is a an emulation of real computer machine.  It needs to have an operating system installed just like a physical computer. This just creates the "virtual" hardware.

    Stay tuned.  I am sure Ed will add more to this in time.

  • Didn't work for me ended up with this on windows 8

    $name = "Client01","Client02", "Server01","Server02", "Server03"

    $name |

    Foreach {

       new-vm $_ -MemoryStartupBytes 512MB -SwitchName "Private Switch" -NewVHDPath "Z:\$_\Virtual Hard Disks\$_.vhdx" -NewVHDSizeBytes 6000000000 }

    Foreach($n in $name)

    {

    if($n -match 'client')

       {

        Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 1024MB -StartupBytes 512MB -Buffer 20

       }

    if($n -match 'server')

     {

      Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 2048MB -StartupBytes 1024MB -Buffer 20

     }

    }

    Get-VM $name | Start-VM