Use PowerShell to Create Virtual Machine in Azure – Part 5

Summary: Learn how to create a virtual machine in Azure by using your own VHD template.

Honorary Scripting Guy, Sean Kearney is here with the last bit of coolness about creating virtual machines in Azure—using a customized template. This post is part of a series. To catch up, read:

Your first challenge is to create a custom virtual machine, which really isn’t a challenge.

Let’s imagine you’ve got a machine that’s set up just the way you want it. Life is good and you’re ready to rock.

The first thing you’ll want to do is make a backup copy of the operating system VHD. If the virtual machine name is ‘HSG-VM’, you can access the location of the VHD file with some Windows PowerShell (of course):

GET-VM ‘HSG-VM’ | Get-VMHardDiskDrive | Select-Object Path

To make a backup of this information, pipe this into Copy-Item in the following manner:

New-ITEM C:Backup –itemtype Directory -force

GET-VM ‘HSG-VM’ | Get-VMHardDiskDrive | foreach { Copy-Item $_.Path –Destination C:Backup }

With this small script, you will have a complete backup of all the VHD files used from this virtual machine. At this point you can log in to the virtual machine as an Administrator and run Sysprep to bring the existing virtual machine to the out-of-box-experience (OOBE) level for deployments:

C:WindowsSystem32sysprepsysprep.exe /quiet /generalize /oobe /shutdown

This will take a few minutes to run. When it’s done, you can upload the operating system to Microsoft Azure.

To send the file, you’ll use the Add-AzureVHD cmdlet. This cmdlet requires two objects: the local path of the VHD you’re trying to send and the URL destination in Azure.

The URL is actually provided by Microsoft Azure, and it is your storage blob. Run this command to get the name of the URL:

Get-AzureStorageAccount | Select-Object -ExpandProperty Endpoints | Where { $_ -match ‘blob’ }

If you have multiple storage blobs, you can specify the specific one. For example, if the account name is HSGStorage, you would use this:

Get-AzureStorageAccount | Select-Object -ExpandProperty Endpoints | Where { $_ -match ‘HSGStorage.blob’ }

With the name identified, you can upload the VHD file directly.

$Source=@(GET-VM ‘HSG-VM’ | Get-VMHardDiskDrive | Select-Object –expandproperty Path)[0]


$Destination=(Get-AzureStorageAccount | Select-Object -ExpandProperty Endpoints |
Where { $_ -match ‘HSGStorage.blob’ })+$VHDFile

Add-AzureVHD –LocalFilePath $Source –Destination $Destination

After the VHD file is added, you can add it as an available image to your personal Azure templates by using the Add-AzureVMImage cmdlet, which will make this VHD available as a template to use.


Add-AzureVMImage –imagename $MyCustomImageName –Medialocation $Destination

Now that you have the VHD file uploaded, you can build a virtual machine in Azure based on this template.

At this point, we are reusing our original script for creating a virtual machine, except we are supplying the custom image name instead:

# Get information needed for our custom image file stored in Azure

$VMimage=((Get-AzureVMImage | where { $_.Label -like ‘ HSG-VMTemplate-Winsrv*’ } |
Sort-Object PublishedDate)[-1]).ImageName

# Get the information for instance size A0

$Size=(Get-AzureRoleSize | Where { $_.InstanceSize –match ‘A0’ }).InstanceSize

# Virtual machine name                 


$VMconfig=New-AzureVMConfig –Name $VMName -InstanceSize $Size -ImageName $VMimage



$AdminPass=Convertto-Securestring –asplaintext ‘NotP@ssw0rd’ -force

$VMProvision = $VMconfig |
Add-AzureProvisioningConfig –windows –password $AdminPass –AdminUserName $AdminName

$VMResult=$VMProvision | New-AzureVM –Servicename ‘HSG-Service’ –waitforboot

With this in place, you can deploy virtual machines in Azure that are based on the image you use in your corporation, rather than rebuilding in the cloud.

I’m certain this is not the last you’ll hear from me about Microsoft Azure and Windows PowerShell. It’s an incredibly powerful solution that IT pros should look into.

I invite you to follow The Scripting Guys on Twitter and Facebook. If you have any questions, send an email to The Scripting Guys at, or post your questions on the Official Scripting Guys Forum. Until next time, remember eat your cmdlets every day with a dash of creativity.

Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy

Comments (2)

  1. Anonymous says:

    This mini series of posts is extremely helpful for scripting VMs in Azure.
    But I miss informations about configuring Azure Networks upfront and assigning fixed internal IP adresses (for the use with Azure VPN) to VMs. If you want to utilize a fixed external Azure IP address, the IP address needs to be setup and configured before the
    VM is being provisioned.

  2. @Thomas

    Thanks for the feedback! I’ll be writing more about PowerShell and Azure a week from now. I will DEFINITELY be incorporating your feedback into the content I provide!


Skip to main content