PowerShell Script to Connect .ISO to a VM [Hyper-V]

I wrote this script a while ago (for the life of me – I cannot remember why) and have been meaning to post it for a while.  Simply put – it connects a .ISO file to a virtual machine under Hyper-V:

 # Function for handling WMI jobs / return values
 Function ProcessResult($localResult, $successString, $failureString)
 {
    #Return success if the return value is "0"
    if ($localResult.ReturnValue -eq 0)
       {write-host $successString} 
  
    #If the return value is not "0" or "4096" then the operation failed
    ElseIf ($localResult.ReturnValue -ne 4096)
       {write-host $failureString "  Error value:" $localResult.ReturnValue}
  
    Else
       {#Get the job object
       $job=[WMI]$localResult.job
  
       #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 "% complete"
           start-sleep 1
  
           #Refresh the job object
           $job=[WMI]$localResult.job}
  
        #A jobstate of "7" means success
        if ($job.JobState -eq 7)
           {write-host $successString}
        Else
           {write-host $failureString
           write-host "ErrorCode:" $job.ErrorCode
           write-host "ErrorDescription" $job.ErrorDescription}
        }
 }
  
 # Prompt for the Hyper-V Server to use
 $HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
  
 # Prompt for the virtual machine to use
 $VMName = Read-Host "Specify the name of the virtual machine"
  
 # Prompt for the ISO file to connect
 $isoPath = Read-Host "Specify the ISO file to connect to the virtual machine"
  
 # Get the management service
 $VMMS = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService -computername $HyperVServer
  
 # Get the virtual machine object
 $VM = gwmi MSVM_ComputerSystem -filter "ElementName='$VMName'" -namespace "root\virtualization" -computername $HyperVServer
  
 # SettingType = 3 ensures that we do not get snapshots
 $SystemSettingData = $VM.getRelated("Msvm_VirtualSystemSettingData") | where {$_.SettingType -eq 3}
  
 # Get the first DVD drive in the system
 $DVDDrive = $SystemSettingData.getRelated("Msvm_ResourceAllocationSettingData") | where{$_.ResourceType -eq 16} | select -first 1
  
 # Make sure the DVD actually exists
 if ($DVDDrive -eq $null) 
    {write-host "No DVD drive exists on that virtual machine"
     exit}
  
 # Check to see if there is already media in the DVD drive
 $existingRASD = $SystemSettingData.getRelated("Msvm_ResourceAllocationSettingData") | where {$_.Parent -eq $DVDDrive.__Path}
  
 # If there is media in the drive - eject it
 if ($existingRASD) {
    $result1 = $VMMS.RemoveVirtualSystemResources($VM, @($existingRASD))
    ProcessResult $result1 "The DVD drive has been cleared." "Failed to clear the DVD drive."}
  
 # Create a new object for a DVD ISO, connected to the DVD drive
 $DVDAllocationCapabilities = (gwmi -computername $HyperVServer -namespace root\virtualization Msvm_AllocationCapabilities `
                               -filter "ResourceType=21 and ResourceSubType='Microsoft Virtual CD/DVD Disk'").__Path.Replace('\', '\\')
 $DVDSettingsData = [wmi](gwmi -computername $HyperVServer -namespace root\virtualization Msvm_SettingsDefineCapabilities `
                          -filter "GroupComponent='$DVDAllocationCapabilities' and ValueRange=0").PartComponent
 $DVDSettingsData.Connection = @($isoPath)
 $DVDSettingsData.Parent = $DVDDrive.__Path
  
 # Add the ISO to the virtual machine
 $result2 = $VMMS.AddVirtualSystemResources($VM, $DVDSettingsData.GetText(1))
  
 ProcessResult $result2 "The ISO file has been connected." "Failed to connect the ISO file."

 

Some details to call out:

  • As there are two places in the script that return a job object – I moved the job object handling code into a separate function.  I think I will be reusing this code a lot in the future :-)
  • A common mistake that I have seen in a lot of scripts that are floating around on the Internet is that people assume that a virtual machine (MSVM_ComputerSystem) will only ever have one settings object (MSVM_VirtualSystemSettingData) associated with it.  This is not true – as there is a new settings object associated with the virtual machine for every snapshot that exists on the virtual machine.  To actually get the real settings object you want to look at the SettingType field – which should be “3” for the active virtual machine settings.
  • As most virtual machines only have a single DVD drive – this script always grabs the first DVD drive it finds to connect the ISO file to.
  • If you try to connect a new media object to a DVD drive that already has media in it – you will fail.  This is why my script checks to see if media is already present – and ejects it if it is.

I have also attached a copy of the script to this blog post.

Cheers,
Ben

InsertISO.zip