{"id":16007,"date":"2014-02-20T13:07:00","date_gmt":"2014-02-20T13:07:00","guid":{"rendered":"https:\/\/aidanfinn.com\/?p=16007"},"modified":"2014-02-20T13:07:00","modified_gmt":"2014-02-20T13:07:00","slug":"script-to-convert-hyper-v-virtual-machine-from-vhd-to-vhdx","status":"publish","type":"post","link":"https:\/\/aidanfinn.com\/?p=16007","title":{"rendered":"Script To Convert Hyper-V Virtual Machine From VHD To VHDX"},"content":{"rendered":"<p>Last year I wrote a script that would allow you to specify a virtual machine, and the script would:<\/p>\n<ol>\n<li>Shut down the VM if running<\/li>\n<li>Seek out any VHD files attached to any of the VM\u2019s controllers<\/li>\n<li>Create VHDX files from those VHD files<\/li>\n<li>Replace the VHD files by attaching the VHDX files to the same controllers and locations in the VM settings<\/li>\n<li>Delete the VHD files<\/li>\n<\/ol>\n<p>In my tests, the script had some issues. But that was nearly a year ago and it was on WS2012 in my lab. The script remained untouched until yesterday. I was chatting with my fellow Hyper-V MVP, <a href=\"http:\/\/workinghardinit.wordpress.com\/\" target=\"_blank\">Didier Van Hoye<\/a> (aka <a href=\"https:\/\/twitter.com\/WorkingHardInIT\" target=\"_blank\">@workinghardinit<\/a>). He told me he was in the process of migrating VMs from an old W2008 R2 cluster to WS2012 and was going to be converting VHD files. Aha! This might be a time for a solution to speed up the process.<\/p>\n<p>I sent the script over to Didier to have a look-see. Would it work. Well, Didier ran a series of tests this morning with guest OSs including W2003 R2 and WS2012. The tests ran flawlessly.<\/p>\n<p>So \u2026 here is the script. FYI there are few things to note:<\/p>\n<ul>\n<li>You might consider putting in a delay loop to test if the VM is actually shut down if you need to shut it down. Put a timeout of 3 minutes in that. The stop-vm cmdlet is async so it shouldn\u2019t cause an issue as it is below, but you might want to take the extra step, just in case.<\/li>\n<li>You might want to comment out the line Remove-VMHardDiskDrive $VHD for your test or pilot runs.<\/li>\n<li>I do not support this script \ud83d\ude42<\/li>\n<li>Run the script and specify the VM name as a parameter.<\/li>\n<\/ul>\n<p>CREDIT: A big thank you to <a href=\"http:\/\/workinghardinit.wordpress.com\/\" target=\"_blank\">Didier Van Hoye<\/a> (aka <a href=\"https:\/\/twitter.com\/WorkingHardInIT\" target=\"_blank\">@workinghardinit<\/a>) for checking my work.<\/p>\n<p>#&#8212;-<\/p>\n<p>[CmdletBinding ()]   <br \/>Param&#160;&#160; (    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; [Parameter(Mandatory=$True)]    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$VMName    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) <\/p>\n<p>#Disable error reporting &#8211; comment out the following line if you need to troubleshoot the script   <br \/>$ErrorActionPreference = &quot;SilentlyContinue&quot; <\/p>\n<p>cls <\/p>\n<p>$VM = Get-VM $VMName   <br \/>$VMStatus = $VM.State <\/p>\n<p>if ($VM.VMid -ne $NULL)   <br \/>{    <br \/>&#160;&#160;&#160; if ($VMStatus -eq &quot;Running&quot;)    <br \/>&#160;&#160;&#160; {&#160;&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Shut down the VM if it is running    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;Shutting down&quot; $VMName    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Stop-VM $VMName&#160;&#160; <br \/>&#160;&#160;&#160; } <\/p>\n<p>&#160;&#160;&#160; #Get the disks in the VM   <br \/>&#160;&#160;&#160; $AllVHD = Get-VMHardDiskDrive $VMName <\/p>\n<p>&#160;&#160;&#160; if ($AllVHD -eq $NULL)   <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; {    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;There are no virtual hard disks to convert&quot;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Exit    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; } <\/p>\n<p>&#160;&#160;&#160; foreach ($VHD in $AllVHD)   <br \/>&#160;&#160;&#160; {    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Get the VM path and create a VHDX file path    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$VHDFile = Get-Item $VHD.Path    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $VHDFormat = (Get-VHD $VHDFile).VhdFormat    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; if ($VHDFormat -eq &quot;VHD&quot;)    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$VHDXFile = $VHDFile + &quot;x&quot; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$ControllerType = $VHD.ControllerType   <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$ControllerNumber = $VHD.ControllerNumber    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; [string]$ControllerLocation = $VHD.ControllerLocation <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;Converting: &quot; $VHDFile &quot;to&quot; $VHDXFile   <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Convert-VHD \u2013Path $VHDFile \u2013DestinationPath $VHDXFile    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sleep 10 <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Reconfigure the Physical Sector Size of the VHDX file to 4 K   <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Set-VHD -Path $VHDXFile -PhysicalSectorSizeBytes 4096    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sleep 10 <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Remove the old VHD   <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;Removing $VHDFile from $VMName&quot;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Remove-VMHardDiskDrive $VHD    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sleep 10    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Replace the VHD with the VHDX    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;Adding $VHDXFile to $VMName&quot;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Add-VMHardDiskDrive -VMName $VMName -Path $VHDXFile -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Danger Will Robinson &#8211; we are going to delete the original VHD &#8211; we hope you have a tested VM backup!   <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;Deleting $VHDFile&quot;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Remove-Item $VHDFile -Force    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; else    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;$VHDFile is already a VHDX file: skipping&quot;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }    <br \/>&#160;&#160;&#160; } <\/p>\n<p>&#160;&#160;&#160; if ($VMStatus -eq &quot;Running&quot;)   <br \/>&#160;&#160;&#160; {&#160;&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Restart the VM if it was running before the conversion    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;Starting&quot; $VMName    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Start-VM $VMName&#160;&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Wait for 10 seconds    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;Waiting for 10 seconds to verify the virtual machine &#8230;&quot;    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sleep 10    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; $VMStatus = $VM.State    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; if ($VMStatus -ne &quot;Running&quot;)    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; {    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #Something went wrong    <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Write-Host &quot;$VMName could not reboot &#8211; please restore the VM from backup&quot;&#160;&#160;&#160;&#160;&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }    <br \/>&#160;&#160;&#160; } <\/p>\n<p>}   <br \/>else    <br \/>{    <br \/>&#160;&#160;&#160; Write-Host $VMName &quot;does not exist on this host&quot;    <br \/>&#160;&#160;&#160; Exit    <br \/>} <\/p>\n<p>Write-Host &quot;Processing of $VMName has completed&quot;<\/p>\n<div id=\"scid:0767317B-992E-4b12-91E0-4F059A8CECA8:b4d8aca2-19b2-48ae-b392-8bfc27b34e2a\" class=\"wlWriterEditableSmartContent\" style=\"float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px\">Technorati Tags: <a href=\"http:\/\/technorati.com\/tags\/Windows+Server+2012\" rel=\"tag\">Windows Server 2012<\/a>,<a href=\"http:\/\/technorati.com\/tags\/Windows+Server+2012+R2\" rel=\"tag\">Windows Server 2012 R2<\/a>,<a href=\"http:\/\/technorati.com\/tags\/Hyper-V\" rel=\"tag\">Hyper-V<\/a>,<a href=\"http:\/\/technorati.com\/tags\/Storage\" rel=\"tag\">Storage<\/a>,<a href=\"http:\/\/technorati.com\/tags\/Virtualisation\" rel=\"tag\">Virtualisation<\/a>,<a href=\"http:\/\/technorati.com\/tags\/PowerShell\" rel=\"tag\">PowerShell<\/a>,<a href=\"http:\/\/technorati.com\/tags\/Scripting\" rel=\"tag\">Scripting<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Last year I wrote a script that would allow you to specify a virtual machine, and the script would: Shut down the VM if running Seek out any VHD files attached to any of the VM\u2019s controllers Create VHDX files from those VHD files Replace the VHD files by attaching the VHDX files to the &hellip; <a href=\"https:\/\/aidanfinn.com\/?p=16007\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Script To Convert Hyper-V Virtual Machine From VHD To VHDX&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[20],"tags":[181,87,189,99,195,118,120],"class_list":["post-16007","post","type-post","status-publish","format-standard","hentry","category-hyper-v","tag-hyper-v","tag-powershell","tag-scripting","tag-storage","tag-virtualisation","tag-windows-server-2012","tag-windows-server-2012-r2"],"aioseo_notices":[],"jetpack_featured_media_url":"","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/aidanfinn.com\/index.php?rest_route=\/wp\/v2\/posts\/16007","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aidanfinn.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/aidanfinn.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/aidanfinn.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/aidanfinn.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=16007"}],"version-history":[{"count":0,"href":"https:\/\/aidanfinn.com\/index.php?rest_route=\/wp\/v2\/posts\/16007\/revisions"}],"wp:attachment":[{"href":"https:\/\/aidanfinn.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=16007"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/aidanfinn.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=16007"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/aidanfinn.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=16007"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}