Prepare a Windows VHD or VHDX to upload to Azure
Applies to: ✔️ Windows VMs
Before you upload a Windows virtual machine (VM) from on-premises to Azure, you must prepare the virtual hard disk (VHD or VHDX). Azure supports both generation 1 and generation 2 VMs that are in VHD file format and that have a fixed-size disk. The maximum size allowed for the OS VHD on a generation 1 VM is 2 TB. You can validate your VHD or VHDX file by refering to this documentation.
You can convert a VHDX file to VHD, convert a dynamically expanding disk to a fixed-size disk, but you can't change a VM's generation. For more information, see Should I create a generation 1 or 2 VM in Hyper-V? and Support for generation 2 VMs on Azure.
For information about the support policy for Azure VMs, see Microsoft server software support for Azure VMs.
Note
The instructions in this article apply to:
- The 64-bit version of Windows Server 2008 R2 and later Windows Server operating systems. For information about running a 32-bit operating system in Azure, see Support for 32-bit operating systems in Azure VMs.
- If any Disaster Recovery tool will be used to migrate the workload, like Azure Site Recovery or Azure Migrate, this process is still required on the Guest OS to prepare the image before the migration.
System File Checker
Run Windows System File Checker utility before generalization of OS image
The System File Checker (SFC) is used to verify and replace Windows system files.
Important
Use an elevated PowerShell session to run the examples in this article.
Run the SFC command:
sfc.exe /scannow
Beginning system scan. This process will take some time.
Beginning verification phase of system scan.
Verification 100% complete.
Windows Resource Protection did not find any integrity violations.
After the SFC scan completes, install Windows Updates and restart the computer.
Set Windows configurations for Azure
Note
Azure platform mounts an ISO file to the DVD-ROM when a Windows VM is created from a generalized image. For this reason, the DVD-ROM must be enabled in the OS in the generalized image. If it is disabled, the Windows VM will be stuck at out-of-box experience (OOBE).
Remove any static persistent routes in the routing table:
- To view the routing table, run
route.exe print
. - Check the Persistence Routes section. If there's a persistent route, use the
route.exe delete
command to remove it.
- To view the routing table, run
Remove the WinHTTP proxy:
netsh.exe winhttp reset proxy
If the VM needs to work with a specific proxy, add a proxy exception for the Azure IP address (168.63.129.16) so the VM can connect to Azure:
$proxyAddress='<your proxy server>' $proxyBypassList='<your list of bypasses>;168.63.129.16' netsh.exe winhttp set proxy $proxyAddress $proxyBypassList
Open DiskPart:
diskpart.exe
Set the disk SAN policy to
Onlineall
:DISKPART> san policy=onlineall DISKPART> exit
Set Coordinated Universal Time (UTC) time for Windows. Also, set the startup type of the Windows time service w32time to Automatic:
Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation -Name RealTimeIsUniversal -Value 1 -Type DWord -Force Set-Service -Name w32time -StartupType Automatic
Set the power profile to high performance:
powercfg.exe /setactive SCHEME_MIN powercfg /setacvalueindex SCHEME_CURRENT SUB_VIDEO VIDEOIDLE 0
Make sure the environmental variables TEMP and TMP are set to their default values:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name TEMP -Value "%SystemRoot%\TEMP" -Type ExpandString -Force Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name TMP -Value "%SystemRoot%\TEMP" -Type ExpandString -Force
For VMs with legacy operating systems (Windows Server 2012 R2 or Windows 8.1 and below), make sure the latest Hyper-V Integration Component Services are installed. For more information, see Hyper-V integration components update for Windows VM.
Note
In a scenario where VMs are to be set up with a disaster recovery solution between the on-premises VMware server and Azure, the Hyper-V Integration Component Services can't be used. If that’s the case, please contact the VMware support to migrate the VM to Azure and make it co-reside in VMware server.
Check the Windows services
Make sure that each of the following Windows services is set to the Windows default value. These services are the minimum that must be configured to ensure VM connectivity. To set the startup settings, run the following example:
Get-Service -Name BFE, Dhcp, Dnscache, IKEEXT, iphlpsvc, nsi, mpssvc, RemoteRegistry |
Where-Object StartType -ne Automatic |
Set-Service -StartupType Automatic
Get-Service -Name Netlogon, Netman, TermService |
Where-Object StartType -ne Manual |
Set-Service -StartupType Manual
Update remote desktop registry settings
Make sure the following settings are configured correctly for remote access:
Note
If you receive an error message when running
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name <string> -Value <object>
,
you can safely ignore it. It means the domain isn't setting that configuration through a Group
Policy Object.
Remote Desktop Protocol (RDP) is enabled:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections -Value 0 -Type DWord -Force Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name fDenyTSConnections -Value 0 -Type DWord -Force
The RDP port is set up correctly using the default port of 3389:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name PortNumber -Value 3389 -Type DWord -Force
When you deploy a VM, the default rules are created for port 3389. To change the port number, do that after the VM is deployed in Azure.
The listener is listening on every network interface:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name LanAdapter -Value 0 -Type DWord -Force
Configure network-level authentication (NLA) mode for the RDP connections:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication -Value 1 -Type DWord -Force
Set the keep-alive value:
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name KeepAliveEnable -Value 1 -Type DWord -Force Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name KeepAliveInterval -Value 1 -Type DWord -Force Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name KeepAliveTimeout -Value 1 -Type DWord -Force
Set the reconnect options:
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name fDisableAutoReconnect -Value 0 -Type DWord -Force Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name fInheritReconnectSame -Value 1 -Type DWord -Force Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name fReconnectSame -Value 0 -Type DWord -Force
Limit the number of concurrent connections:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name MaxInstanceCount -Value 4294967295 -Type DWord -Force
Remove any self-signed certificates tied to the RDP listener:
if ((Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp').Property -contains 'SSLCertificateSHA1Hash') { Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name SSLCertificateSHA1Hash -Force }
This code ensures that you can connect when you deploy the VM. You can also review these settings after the VM is deployed in Azure.
If the VM is part of a domain, check the following policies to make sure the previous settings aren't reverted.
Goal Policy Value RDP is enabled Computer Configuration\Policies\Windows Settings\Administrative Templates\Components\Remote Desktop Services\Remote Desktop Session Host\Connections Allow users to connect remotely by using Remote Desktop NLA group policy Settings\Administrative Templates\Components\Remote Desktop Services\Remote Desktop Session Host\Security Require user authentication for remote access by using NLA Keep-alive settings Computer Configuration\Policies\Windows Settings\Administrative Templates\Windows Components\Remote Desktop Services\Remote Desktop Session Host\Connections Configure keep-alive connection interval Reconnect settings Computer Configuration\Policies\Windows Settings\Administrative Templates\Windows Components\Remote Desktop Services\Remote Desktop Session Host\Connections Reconnect automatically Limited number of connection settings Computer Configuration\Policies\Windows Settings\Administrative Templates\Windows Components\Remote Desktop Services\Remote Desktop Session Host\Connections Limit number of connections
Configure Windows Firewall rules
Turn on Windows Firewall on the three profiles (domain, standard, and public):
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled True
Run the following example to allow WinRM through the three firewall profiles (domain, private, and public), and enable the PowerShell remote service:
Enable-PSRemoting -Force
Note
When this command runs, it enables the appropriate firewall rules automatically.
Enable the following firewall rules to allow the RDP traffic:
Get-NetFirewallRule -DisplayGroup 'Remote Desktop' | Set-NetFirewallRule -Enabled True
Enable the rule for file and printer sharing so the VM can respond to ping requests inside the virtual network:
Set-NetFirewallRule -Name FPS-ICMP4-ERQ-In -Enabled True
Create a rule for the Azure platform network:
New-NetFirewallRule -DisplayName AzurePlatform -Direction Inbound -RemoteAddress 168.63.129.16 -Profile Any -Action Allow -EdgeTraversalPolicy Allow New-NetFirewallRule -DisplayName AzurePlatform -Direction Outbound -RemoteAddress 168.63.129.16 -Profile Any -Action Allow
Important
168.63.129.16 is a special public IP address that is owned by Microsoft for Azure. For more information, see What is IP address 168.63.129.16.
If the VM is part of a domain, check the following Microsoft Entra policies to make sure the previous settings aren't reverted.
Goal Policy Value Enable the Windows Firewall profiles Computer Configuration\Policies\Windows Settings\Administrative Templates\Network\Network Connection\Windows Firewall\Domain Profile\Windows Firewall Protect all network connections Enable RDP Computer Configuration\Policies\Windows Settings\Administrative Templates\Network\Network Connection\Windows Firewall\Domain Profile\Windows Firewall Allow inbound Remote Desktop exceptions Computer Configuration\Policies\Windows Settings\Administrative Templates\Network\Network Connection\Windows Firewall\Standard Profile\Windows Firewall Allow inbound Remote Desktop exceptions Enable ICMP-V4 Computer Configuration\Policies\Windows Settings\Administrative Templates\Network\Network Connection\Windows Firewall\Domain Profile\Windows Firewall Allow ICMP exceptions Computer Configuration\Policies\Windows Settings\Administrative Templates\Network\Network Connection\Windows Firewall\Standard Profile\Windows Firewall Allow ICMP exceptions
Verify the VM
Make sure the VM is healthy, secure, and RDP accessible:
To make sure the disk is healthy and consistent, check the disk at the next VM restart:
chkdsk.exe /f
Make sure the report shows a clean and healthy disk.
Set the Boot Configuration Data (BCD) settings.
cmd bcdedit.exe /set "{bootmgr}" integrityservices enable bcdedit.exe /set "{default}" device partition=C: bcdedit.exe /set "{default}" integrityservices enable bcdedit.exe /set "{default}" recoveryenabled Off bcdedit.exe /set "{default}" osdevice partition=C: bcdedit.exe /set "{default}" bootstatuspolicy IgnoreAllFailures #Enable Serial Console Feature bcdedit.exe /set "{bootmgr}" displaybootmenu yes bcdedit.exe /set "{bootmgr}" timeout 5 bcdedit.exe /set "{bootmgr}" bootems yes bcdedit.exe /ems "{current}" ON bcdedit.exe /emssettings EMSPORT:1 EMSBAUDRATE:115200 exit
The dump log can be helpful in troubleshooting Windows crash issues. Enable the dump log collection:
# Set up the guest OS to collect a kernel dump on an OS crash event Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl' -Name CrashDumpEnabled -Type DWord -Force -Value 2 Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl' -Name DumpFile -Type ExpandString -Force -Value "%SystemRoot%\MEMORY.DMP" Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl' -Name NMICrashDump -Type DWord -Force -Value 1 # Set up the guest OS to collect user mode dumps on a service crash event $key = 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' if ((Test-Path -Path $key) -eq $false) {(New-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting' -Name LocalDumps)} New-ItemProperty -Path $key -Name DumpFolder -Type ExpandString -Force -Value 'C:\CrashDumps' New-ItemProperty -Path $key -Name CrashCount -Type DWord -Force -Value 10 New-ItemProperty -Path $key -Name DumpType -Type DWord -Force -Value 2 Set-Service -Name WerSvc -StartupType Manual
Verify that the Windows Management Instrumentation (WMI) repository is consistent:
winmgmt.exe /verifyrepository
If the repository is corrupted, see WMI: Repository corruption or not.
Make sure no other applications than TermService are using port 3389. This port is used for the RDP service in Azure. To see which ports are used on the VM, run
netstat.exe -anob
:netstat.exe -anob
The following is an example.
netstat.exe -anob | findstr 3389 TCP 0.0.0.0:3389 0.0.0.0:0 LISTENING 4056 TCP [::]:3389 [::]:0 LISTENING 4056 UDP 0.0.0.0:3389 *:* 4056 UDP [::]:3389 *:* 4056 tasklist /svc | findstr 4056 svchost.exe 4056 TermService
To upload a Windows VHD that's a domain controller:
Follow these extra steps to prepare the disk.
Make sure you know the Directory Services Restore Mode (DSRM) password in case you ever have to start the VM in DSRM. For more information, see Set a DSRM password.
Make sure you know the built-in administrator account and password. You might want to reset the current local administrator password and make sure you can use this account to sign in to Windows through the RDP connection. This access permission is controlled by the "Allow log on through Remote Desktop Services" Group Policy Object. View this object in the Local Group Policy Editor:
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment
Check the following Microsoft Entra policies to make sure they're not blocking RDP access:
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\Deny access to this computer from the network
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\Deny log on through Remote Desktop Services
Check the following Microsoft Entra policy to make sure they're not removing any of the required access accounts:
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\Access this computer from the network
The policy should list the following groups:
Administrators
Backup Operators
Everyone
Users
Restart the VM to make sure that Windows is still healthy and can be reached through the RDP connection. At this point, consider creating a VM on your local Hyper-V server to make sure the VM starts completely. Then test to make sure you can reach the VM through RDP.
Remove any extra Transport Driver Interface (TDI) filters. For example, remove software that analyzes TCP packets or extra firewalls.
Uninstall any other third-party software or driver that's related to physical components or any other virtualization technology.
Install Windows updates
Note
To avoid an accidental reboot during the VM provisioning, we recommend completing all Windows update installations and to make sure there’s no pending restart. One way to do this is to install all Windows updates and to reboot the VM before performing the migration to Azure.
If you also need to do a generalization of the OS (sysprep), you must update Windows and restart the VM before running the Sysprep command.
Ideally, you should keep the machine updated to the patch level, if this isn't possible, make sure the following updates are installed. To get the latest updates, see the Windows update history pages: Windows 10, and Windows Server 2019, Windows 8.1, and Windows Server 2012 R2 and Windows 7 SP1, and Windows Server 2008 R2 SP1.
Component | Binary | Windows 7 SP1, Windows Server 2008 R2 SP1 | Windows 8, Windows Server 2012 | Windows 8.1, Windows Server 2012 R2 | Windows 10 v1607, Windows Server 2016 v1607 | Windows 10 v1703 | Windows 10 v1709, Windows Server 2016 v1709 | Windows 10 v1803, Windows Server 2016 v1803 |
---|---|---|---|---|---|---|---|---|
Storage | disk.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.17638 / 6.2.9200.21757 - KB3137061 | 6.3.9600.18203 - KB3137061 | - | - | - | - |
storport.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.17188 / 6.2.9200.21306 - KB3018489 | 6.3.9600.18573 - KB4022726 | 10.0.14393.1358 - KB4022715 | 10.0.15063.332 | - | - | |
ntfs.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.17623 / 6.2.9200.21743 - KB3121255 | 6.3.9600.18654 - KB4022726 | 10.0.14393.1198 - KB4022715 | 10.0.15063.447 | - | - | |
Iologmsg.dll | 6.1.7601.23403 - KB3125574 | 6.2.9200.16384 - KB2995387 | - | - | - | - | - | |
Classpnp.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.17061 / 6.2.9200.21180 - KB2995387 | 6.3.9600.18334 - KB3172614 | 10.0.14393.953 - KB4022715 | - | - | - | |
Volsnap.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.17047 / 6.2.9200.21165 - KB2975331 | 6.3.9600.18265 - KB3145384 | - | 10.0.15063.0 | - | - | |
partmgr.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.16681 - KB2877114 | 6.3.9600.17401 - KB3000850 | 10.0.14393.953 - KB4022715 | 10.0.15063.0 | - | - | |
volmgr.sys | 10.0.15063.0 | - | - | |||||
Volmgrx.sys | 6.1.7601.23403 - KB3125574 | - | - | - | 10.0.15063.0 | - | - | |
Msiscsi.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.21006 - KB2955163 | 6.3.9600.18624 - KB4022726 | 10.0.14393.1066 - KB4022715 | 10.0.15063.447 | - | - | |
Msdsm.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.21474 - KB3046101 | 6.3.9600.18592 - KB4022726 | - | - | - | - | |
Mpio.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.21190 - KB3046101 | 6.3.9600.18616 - KB4022726 | 10.0.14393.1198 - KB4022715 | - | - | - | |
vmstorfl.sys | 6.3.9600.18907 - KB4072650 | 6.3.9600.18080 - KB3063109 | 6.3.9600.18907 - KB4072650 | 10.0.14393.2007 - KB4345418 | 10.0.15063.850 - KB4345419 | 10.0.16299.371 - KB4345420 | - | |
Fveapi.dll | 6.1.7601.23311 - KB3125574 | 6.2.9200.20930 - KB2930244 | 6.3.9600.18294 - KB3172614 | 10.0.14393.576 - KB4022715 | - | - | - | |
Fveapibase.dll | 6.1.7601.23403 - KB3125574 | 6.2.9200.20930 - KB2930244 | 6.3.9600.17415 - KB3172614 | 10.0.14393.206 - KB4022715 | - | - | - | |
Network | netvsc.sys | - | - | - | 10.0.14393.1198 - KB4022715 | 10.0.15063.250 - KB4020001 | - | - |
mrxsmb10.sys | 6.1.7601.23816 - KB4022722 | 6.2.9200.22108 - KB4022724 | 6.3.9600.18603 - KB4022726 | 10.0.14393.479 - KB4022715 | 10.0.15063.483 | - | - | |
mrxsmb20.sys | 6.1.7601.23816 - KB4022722 | 6.2.9200.21548 - KB4022724 | 6.3.9600.18586 - KB4022726 | 10.0.14393.953 - KB4022715 | 10.0.15063.483 | - | - | |
mrxsmb.sys | 6.1.7601.23816 - KB4022722 | 6.2.9200.22074 - KB4022724 | 6.3.9600.18586 - KB4022726 | 10.0.14393.953 - KB4022715 | 10.0.15063.0 | - | - | |
tcpip.sys | 6.1.7601.23761 - KB4022722 | 6.2.9200.22070 - KB4022724 | 6.3.9600.18478 - KB4022726 | 10.0.14393.1358 - KB4022715 | 10.0.15063.447 | - | - | |
http.sys | 6.1.7601.23403 - KB3125574 | 6.2.9200.17285 - KB3042553 | 6.3.9600.18574 - KB4022726 | 10.0.14393.251 - KB4022715 | 10.0.15063.483 | - | - | |
vmswitch.sys | 6.1.7601.23727 - KB4022719 | 6.2.9200.22117 - KB4022724 | 6.3.9600.18654 - KB4022726 | 10.0.14393.1358 - KB4022715 | 10.0.15063.138 | - | - | |
Core | ntoskrnl.exe | 6.1.7601.23807 - KB4022719 | 6.2.9200.22170 - KB4022718 | 6.3.9600.18696 - KB4022726 | 10.0.14393.1358 - KB4022715 | 10.0.15063.483 | - | - |
Remote Desktop Services | rdpcorets.dll | 6.2.9200.21506 - KB4022719 | 6.2.9200.22104 - KB4022724 | 6.3.9600.18619 - KB4022726 | 10.0.14393.1198 - KB4022715 | 10.0.15063.0 | - | - |
termsrv.dll | 6.1.7601.23403 - KB3125574 | 6.2.9200.17048 - KB2973501 | 6.3.9600.17415 - KB3000850 | 10.0.14393.0 - KB4022715 | 10.0.15063.0 | - | - | |
termdd.sys | 6.1.7601.23403 - KB3125574 | - | - | - | - | - | - | |
win32k.sys | 6.1.7601.23807 - KB4022719 | 6.2.9200.22168 - KB4022718 | 6.3.9600.18698 - KB4022726 | 10.0.14393.594 - KB4022715 | - | - | - | |
rdpdd.dll | 6.1.7601.23403 - KB3125574 | - | - | - | - | - | - | |
rdpwd.sys | 6.1.7601.23403 - KB3125574 | - | - | - | - | - | - | |
Security | MS17-010 | KB4012212 | KB4012213 | KB4012213 | KB4012606 | KB4012606 | - | - |
KB4012216 | KB4013198 | KB4013198 | - | - | ||||
KB4012215 | KB4012214 | KB4012216 | KB4013429 | KB4013429 | - | - | ||
KB4012217 | KB4013429 | KB4013429 | - | - | ||||
CVE-2018-0886 | KB4103718 | KB4103730 | KB4103725 | KB4103723 | KB4103731 | KB4103727 | KB4103721 | |
KB4103712 | KB4103726 | KB4103715 |
Note
To avoid an accidental reboot during VM provisioning, we recommend ensuring that all Windows
Update installations are finished and that no updates are pending. One way to do this is to
install all possible Windows updates and reboot once before you run the sysprep.exe
command.
Determine when to use Sysprep
System Preparation Tool (sysprep.exe
) is a process you can run to reset a Windows installation.
Sysprep provides an "out of the box" experience by removing all personal data and resetting several
components.
You typically run sysprep.exe
to create a template from which you can deploy several other VMs
that have a specific configuration. The template is called a generalized image.
To create only one VM from one disk, you don't have to use Sysprep. Instead, you can create the VM from a specialized image. For information about how to create a VM from a specialized disk, see:
To create a generalized image, you need to run Sysprep. For more information, see How to use Sysprep: An introduction.
Not every role or application that's installed on a Windows-based computer supports generalized images. Before you use this procedure, make sure Sysprep supports the role of the computer. For more information, see Sysprep support for server roles.
In particular, Sysprep requires the drives to be fully decrypted before execution. If you have enabled encryption on your VM, disable it before running Sysprep.
Generalize a VHD
Note
If you're creating a generalized image from an existing Azure VM, we recommend to remove the VM extensions before running the sysprep.
Note
After you run sysprep.exe
in the following steps, turn off the VM. Don't turn it back on until
you create an image from it in Azure.
Sign in to the Windows VM.
Run a PowerShell session as an administrator.
Delete the panther directory (C:\Windows\Panther).
Change the directory to
%windir%\system32\sysprep
. Then runsysprep.exe
.In the System Preparation Tool dialog box, select Enter System Out-of-Box Experience (OOBE), and make sure the Generalize checkbox is selected.
In Shutdown Options, select Shutdown.
Select OK.
When Sysprep finishes, shut down the VM. Don't use Restart to shut down the VM.
Now the VHD is ready to be uploaded. For more information about how to create a VM from a generalized disk, see Upload a generalized VHD and use it to create a new VM in Azure.
Note
A custom unattend.xml file is not supported. Although we do support the additionalUnattendContent property, that provides only limited support for adding microsoft-windows-shell-setup options into the unattend.xml file that the Azure provisioning agent uses. You can use, for example, additionalUnattendContent to add FirstLogonCommands and LogonCommands. For more information, see additionalUnattendContent FirstLogonCommands example.
Convert the virtual disk to a fixed size VHD
Note
If you're going to use Azure PowerShell to upload your disk to Azure and you have Hyper-V enabled, this step is optional. Add-AzVHD will perform it for you.
Use one of the methods in this section to convert and resize your virtual disk to the required format for Azure:
Back up the VM before you run the virtual disk conversion or resize process.
Make sure that the Windows VHD works correctly on the local server. Resolve any errors within the VM itself before you try to convert or upload it to Azure.
Convert the virtual disk to type fixed.
Resize the virtual disk to meet Azure requirements:
Disks in Azure must have a virtual size aligned to 1 MiB. If your VHD is a fraction of 1 MiB, you'll need to resize the disk to a multiple of 1 MiB. Disks that are fractions of a MiB cause errors when creating images from the uploaded VHD. To verify the size you can use the PowerShell Get-VHD cmdlet to show "Size", which must be a multiple of 1 MiB in Azure, and "FileSize", which will be equal to "Size" plus 512 bytes for the VHD footer.
$vhd = Get-VHD -Path C:\test\MyNewVM.vhd $vhd.Size % 1MB 0 $vhd.FileSize - $vhd.Size 512
The maximum size allowed for the OS VHD with a generation 1 VM is 2,048 GiB (2 TiB),
The maximum size for a data disk is 32,767 GiB (32 TiB).
Note
- If you are preparing a Windows OS disk after you convert to a fixed disk and resize if needed, create a VM that uses the disk. Start and sign in to the VM and continue with the sections in this article to finish preparing it for uploading.
- If you are preparing a data disk you may stop with this section and proceed to uploading your disk.
Use Hyper-V Manager to convert the disk
- Open Hyper-V Manager and select your local computer on the left. In the menu above the computer list, select Action > Edit Disk.
- On the Locate Virtual Hard Disk page, select your virtual disk.
- On the Choose Action page, select Convert > Next.
- To convert from VHDX, select VHD > Next.
- To convert from a dynamically expanding disk, select Fixed size > Next.
- Locate and select a path to save the new VHD file.
- Select Finish.
Use PowerShell to convert the disk
You can convert a virtual disk using the Convert-VHD cmdlet in PowerShell. If you need information about installing this cmdlet see Install the Hyper-V role.
Note
If you're going to use Azure PowerShell to upload your disk to Azure and you have Hyper-V enabled, this step is optional. Add-AzVHD will perform it for you.
The following example converts the disk from VHDX to VHD. It also converts the disk from a dynamically expanding disk to a fixed-size disk.
Convert-VHD -Path C:\test\MyVM.vhdx -DestinationPath C:\test\MyNewVM.vhd -VHDType Fixed
In this example, replace the value for Path with the path to the virtual hard disk that you want to convert. Replace the value for DestinationPath with the new path and name of the converted disk.
Use Hyper-V Manager to resize the disk
Note
If you're going to use Azure PowerShell to upload your disk to Azure and you have Hyper-V enabled, this step is optional. Add-AzVHD will perform it for you.
- Open Hyper-V Manager and select your local computer on the left. In the menu above the computer list, select Action > Edit Disk.
- On the Locate Virtual Hard Disk page, select your virtual disk.
- On the Choose Action page, select Expand > Next.
- On the Locate Virtual Hard Disk page, enter the new size in GiB > Next.
- Select Finish.
Use PowerShell to resize the disk
Note
If you're going to use Azure PowerShell to upload your disk to Azure and you have Hyper-V enabled, this step is optional. Add-AzVHD will perform it for you.
You can resize a virtual disk using the Resize-VHD cmdlet in PowerShell. If you need information about installing this cmdlet see Install the Hyper-V role.
The following example resizes the disk from 100.5 MiB to 101 MiB to meet the Azure alignment requirement.
Resize-VHD -Path C:\test\MyNewVM.vhd -SizeBytes 105906176
In this example, replace the value for Path with the path to the virtual hard disk that you want to resize. Replace the value for SizeBytes with the new size in bytes for the disk.
Convert from VMware VMDK disk format
If you have a Windows VM image in the VMDK file format, then you can use Azure Migrate to convert the VMDK and upload it to Azure.
Complete the recommended configurations
The following settings don't affect VHD uploading. However, we strongly recommend that you configured them.
Install the Azure Virtual Machine Agent. Then you can enable VM extensions. The VM extensions implement most of the critical functionality that you might want to use with your VMs. You'll need the extensions, for example, to reset passwords or configure RDP. For more information, see the Azure Virtual Machine Agent overview.
After you create the VM in Azure, we recommend that you put the page file on the temporal drive volume to improve performance. You can set up the file placement as follows:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management' -Name PagingFiles -Value 'D:\pagefile.sys' -Type MultiString -Force
If a data disk is attached to the VM, the temporal drive volume's letter is typically D. This designation could be different, depending on your settings and the number of available drives.
- We recommend disabling script blockers that might be provided by antivirus software. They might interfere and block the Windows Provisioning Agent scripts executed when you deploy a new VM from your image.
Tip
Optional Use DISM to optimize your image and reduce your VM's first boot time.
To optimize your image, mount your VHD by double-clicking on it in Windows explorer, and then run DISM with the /optimize-image
parameter.
DISM /image:D:\ /optimize-image /boot
Where D: is the mounted VHD's path.
Running DISM /optimize-image
should be the last modification you make to your VHD. If you make any changes to your VHD prior to deployment, you'll have to run DISM /optimize-image
again.