Scripting VM Creation with Hyper-V

People have been bugging me for this for a while – so here we go.

Here are the VBScripts / PowerShell scripts to create a basic virtual machine:


Option Explicit
Dim HyperVServer
Dim VMName
Dim WMIService
Dim VSManagementService
Dim VSGlobalSettingData
Dim Result
Dim Job
Dim InParam
Dim OutParam
'Prompt for the Hyper-V Server to use
HyperVServer = InputBox("Specify the Hyper-V Server to create the virtual machine on:")
'Prompt for the new VM name
VMName = InputBox("Specify the name for the new virtual machine:")
'Get an instance of the WMI Service in the virtualization namespace.
Set WMIService = GetObject("winmgmts:\\" & HyperVServer & "\root\virtualization")
'Get the VirtualSystemManagementService object
Set VSManagementService = WMIService.ExecQuery("SELECT * FROM Msvm_VirtualSystemManagementService").ItemIndex(0)
' Initialize a new global settings for the VM
Set VSGlobalSettingData = WMIService.Get("Msvm_VirtualSystemGlobalSettingData").SpawnInstance_()
'Set the VM name
VSGlobalSettingData.ElementName = VMName
'Setup the input parameter list
Set InParam = VSManagementService.Methods_("DefineVirtualSystem").InParameters.SpawnInstance_()
InParam.SystemSettingData = VSGlobalSettingData.GetText_(1) 
'Execute the method and store the results in OutParam
Set OutParam = VSManagementService.ExecMethod_("DefineVirtualSystem", InParam) 
'Check to see if the job completed synchronously
if (OutParam.ReturnValue = 0) then
   Wscript.Echo "Virtual machine created."
elseif (OutParam.ReturnValue <> 4096) then
   Wscript.Echo "Failed to create virtual machine"
   'Get the job object
   set Job = WMIService.Get(OutParam.Job)
    'Wait for the job to complete (3 == starting, 4 == running)
   while (Job.JobState = 3) or (Job.JobState = 4)
      Wscript.Echo Job.PercentComplete
      'Refresh the job object
      set Job = WMIService.Get(OutParam.Job)
   'Provide details if the job fails (7 == complete)
   if (Job.JobState <> 7) then
      Wscript.Echo "Failed to create virtual machine"
      Wscript.Echo "ErrorCode:" & Job.ErrorCode
      Wscript.Echo "ErrorDescription:" & Job.ErrorDescription
      Wscript.Echo "Virtual machine created."
   end If
end if


# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to create the virtual machine on"
# Get name for new VM
$VMName = Read-Host "Specify the name for the new virtual machine"
# Create new MSVM_VirtualSystemGlobalSettingData object
$wmiClassString = "\\" + $HyperVServer + "\root\virtualization:Msvm_VirtualSystemGlobalSettingData"
$wmiClass = [WMIClass]$wmiClassString
$newVSGlobalSettingData = $wmiClass.CreateInstance()
# wait for the new object to be populated
while ($newVSGlobalSettingData.psbase.Properties -eq $null) {}
# Set the VM name
$newVSGlobalSettingData.psbase.Properties.Item("ElementName").value = $VMName
# Get the VirtualSystemManagementService object
$VSManagementService = gwmi MSVM_VirtualSystemManagementService -namespace "root\virtualization" -computername $HyperVServer
# Create the VM
$result = $VSManagementService.DefineVirtualSystem($newVSGlobalSettingData.psbase.GetText(1))
#Return success if the return value is "0"
if ($Result.ReturnValue -eq 0)
   {write-host "Virtual machine created."} 
#If the return value is not "0" or "4096" then the operation failed
ElseIf ($Result.ReturnValue -ne 4096)
   {write-host "Failed to create virtual machine"}
   {#Get the job object
    #Provide updates if the jobstate is "3" (starting) or "4" (running)
    while ($job.JobState -eq 3 -or $job.JobState -eq 4)
      {write-host $job.PercentComplete
       start-sleep 1
       #Refresh the job object
     #A jobstate of "7" means success
    if ($job.JobState -eq 7)
       {write-host "Virtual machine created."}
       {write-host "Failed to create virtual machine"
        write-host "ErrorCode:" $job.ErrorCode
        write-host "ErrorDescription" $job.ErrorDescription}

The basic concept here is that you need to create a new instance of Msvm_VirtualSystemGlobalSettingData and then pass it to the DefineVirtualSystem method on the MSVM_VirtualSystemManagementService object.

This will create a new blank virtual machine with no virtual hard disks, network adapters, etc… (I will dig into creating virtual machines with all these bits later).

Note that both of these scripts allow you to specify a remote Hyper-V server to create the virtual machine on.