Prepare the Virtual Machine for Image Capture
This section shows you how to generalize your Windows virtual machine. This removes all your personal account information, among other things. You will typically want to do this when you want to use this Virtual Machine image to quickly deploy similar virtual machines.
Please note that the virtual machine cannot be logged into via Remote Desktop Protocol once it is generalized, since the process removes all user accounts. This is an irreversible change.
- Sign in to your Windows virtual machine. In the Azure portal, navigate through Browse >Virtual machines > Your Windows virtual machine > Connect.
- Open a Command Prompt window as an administrator.
- Change the directory to
%windir%\system32\sysprep, and then run sysprep.exe. Failure to do this will result in the inability for nodes to communicate.
- In the System Preparation Tool dialog box, do the following:
- In System Cleanup Action, select Enter System Out-of-Box Experience (OOBE) and make sure that Generalize is checked. For more information about using Sysprep, see How to Use Sysprep: An Introduction.
- In Shutdown Options, selectShutdown
- Click OK.
Sysprep shuts down the virtual machine. Its status changes to Stopped in the Azure portal.
Capture the Virtual Machine
The following details are required for this section:
- Resource Group
- Virtual Machine Name to create image from
Depending on your Azure setup you may require your Azure Subscription ID. This can be found by navigating through Browse > Subscriptions.
You can capture the generalized Windows VM by using Azure PowerShell. This section will show you the steps.
This article assumes that you have installed Azure PowerShell version 1.0.x. We recommend using this version since new Resource Manager features will not be added to older PowerShell versions. Read Azure PowerShell 1.0 to know more about the version differences.
Open Azure PowerShell 1.0.x and sign in to your Azure account.
or open Windows Powershell
Import-Module AzureRM.Compute Login-AzureRmAccount
- If the subscription ID that is selected by default is different from the one you want to work in, use either of the following to set the right subscription.
Set-AzureRmContext -SubscriptionId "xxxx-xxxx-xxxx-xxxx"
Select-AzureRmSubscription -SubscriptionId "xxxx-xxxx-xxxx-xxxx"
You can find the subscriptions that your Azure account has by using the command:
- Now you will need to deallocate the resources that are used by this virtual machine by using this command:
Stop-AzureRmVM -ResourceGroupName YourResourceGroup -Name YourWindowsVM
You will see that the Status for the VM on the Azure portal has changed from "Stopped" to "Stopped (deallocated)"
You can also find out the status of your virtual machine in PowerShell by using:
$vm = Get-AzureRmVM -ResourceGroupName YourResourceGroup -Name YourWindowsVM -status $vm.Statuses
The DisplayStatus field corresponds to the Status shown in the Azure portal.
Next, you need to set the status of the virtual machine to "Generalized". Note that you will need to do this because the generalization step above (
sysprep) does not do it in a way that Azure can understand.
Set-AzureRmVm -ResourceGroupName YourResourceGroup -Name YourWindowsVM -Generalized
The generalized state as set above will not be shown on the portal. However, you can verify it by using the Get-AzureRmVM command as shown in the tip above.
Capture the virtual machine image to a destination storage container by using this command.Container names must be 3-63 characters in length and may contain only lower-case alphanumeric characters and hyphen. Hyphen must be preceded and followed by an alphanumeric character
Save-AzureRmVMImage -ResourceGroupName YourResourceGroup -VMName YourWindowsVM -DestinationContainerName YourImagesContainer -VHDNamePrefix YourTemplatePrefix -Path Yourlocalfilepath\Filename.json
-Pathvariable is optional. You can use it to save the JSON template locally. The
-DestinationContainerNamevariable is the name of the container that you want to hold your images in. The URL of the image that is stored will be similar to
It will be created in the same storage account as that of the original virtual machine.
To find the location of your image, open the local JSON file template. Go to the resources > storageProfile > osDisk > image > uri0 section for the complete path of your image. As of now, there is no easy way to check these images on the portal, since the system container in the storage account is hidden. For this reason, although the
-Pathvariable is optional, you definitely want to use it to save the template locally and to easily find out the image URL. Alternatively, you can find this out using a tool called the Azure Storage Explorer which is explained in the steps in the next section
The following configuration items need to be updated in the script:
$vmImageName = "YourWindowsVM";
$resourceGroupName = "YourResourceGroup";
$destinationContainerName = "YourImagesContainer";
$vhdNamePrefix = "YourTemplatePrefix"
$jsonImagePath = "Yourlocalfilepath\Filename.json";
Creating a Windows Image - Complete Script
Import-Module AzureRM.Compute Login-AzureRmAccount #Name of the machine being used to create image $vmImageName = "YourWindowsVM"; #Resource group name created in 'Setting Up a Virtual Network and Virtual Machine in Windows Azure' $resourceGroupName = "YourResourceGroup"; #Container to store image. Container names must be 3-63 characters in length and may contain only lower-case alphanumeric characters and hyphen. #Hyphen must be preceded and followed by an alphanumeric character $destinationContainerName = "YourImagesContainer"; #Prefix for image name $vhdNamePrefix = "YourTemplatePrefix" #Location to output json file containing image details $jsonImagePath = "Yourlocalfilepath\Filename.json"; Write-Host "Stopping VM :" $vmImageName Stop-AzureRmVM -ResourceGroupName $resourceGroupName -Name $vmImageName -Force Write-Host "Stopped VM :" $vmImageName Write-Host "Generalizing VM :" $vmImageName Set-AzureRmVm -ResourceGroupName $resourceGroupName -Name $vmImageName -Generalized Write-Host "Generalized VM :" $vmImageName Write-Host "Save VM Image JSON :" $vmImageName " - " $jsonImagePath Save-AzureRmVMImage -ResourceGroupName $resourceGroupName -VMName $vmImageName -DestinationContainerName $destinationContainerName -VHDNamePrefix $vhdNamePrefix -Path $jsonImagePath -Overwrite