Create Backups of Virtual Machines in Windows Azure by using PowerShell

Summary: Guest blogger, Keith Mayer, talks about using Windows PowerShell to manage cloud-based backups.

Microsoft Scripting Guy, Ed Wilson, is here. Welcome back Keith Mayer as our guest blogger today. This is Part 1 of a two-part series. In Part 2, we’ll restore virtual machines in Windows Azure from these backups.

Photo of Keith Mayer

Keith Mayer is a senior technical evangelist at Microsoft, and he focuses on the Windows infrastructure, datacenter virtualization, systems management, and the private cloud. Keith has over 20 years of experience as a technical leader of complex IT projects, in diverse roles, including network engineer, IT manager, technical instructor, and consultant. He has consulted and trained thousands of IT professionals worldwide on the design and implementation of enterprise technology solutions.

You can find Keith online at

Windows Azure Infrastructure Services provides the ability to easily provision or migrate storage, virtual machines, and virtual networks to the global Windows Azure cloud platform by using a cost-effective Pay-As-You-Go model. In my prior Weekend Scripter posts, Getting Started with Windows Azure and PowerShell and Remoting the Cloud with Windows Azure and PowerShell, I provided an introduction to using Windows PowerShell for automated provisioning of Windows Azure cloud fabric resources and workloads running inside virtual machines in Windows Azure.

Once you’ve provisioned a few lab virtual machines on Windows Azure, you’ll likely want to create a backup copy of each virtual machine. This is particularly useful in test lab scenarios, so that you can quickly revert virtual machines back to a known state prior to performing a set of tests.

When you are working in the on-premises world, this is typically performed via virtual machine backup, snapshot, or checkpoint capabilities. In Windows Azure, back up and restore of virtual hard disks can be quickly performed in the cloud with the Windows Azure PowerShell Module by leveraging the Start-AzureStorageBlobCopy cmdlet. However, there’s a bit of work we’ll need to do upfront to capture the information we’ll need for completing this process.

In this post, we’ll step through the process of building a Windows PowerShell script to back up virtual machines in Windows Azure. At the end of this post, I’ve provided a link to the next step, restoring virtual machines in Windows Azure, so that you’ll have the complete end-to-end process.

To back up virtual machines in Windows Azure, we’ll step through the following tasks:

  • Select a virtual machine to back up
  • Identify each virtual hard disk
  • Create a cloud storage container for storing backups
  • Back up virtual machines to cloud storage in Windows Azure

Note  To learn more about the basics of Windows Azure Infrastructure Services, you might also be interested in the “Early Experts” Cloud Quest and our scenario-based Cloud Labs step-by-step guides. Both are free online study resources that provide hands-on lab exercises for leveraging Windows Azure and building key IT pro cloud scenarios.

Select virtual machine to back up

The virtual machine you want to back up and restore can be selected by using the Get-AzureVM cmdlet. Running Get-AzureVM alone returns a list of virtual machines that are currently provisioned in Windows Azure.

Image of command output
  Get-AzureVM cmdlet output

To select a particular virtual machine, you can pass the ServiceName and Name values as parameters and set the output to a new Windows PowerShell variable.

Image of command output
  Selecting a Windows Azure virtual machine

Now our selected Windows Azure virtual machine can be referenced by using the variable $vm in the remainder of our script.

To capture a valid backup of each virtual hard disk, we also need to temporarily shut down the virtual machine to a state where the virtual machine is not running, but its configuration is kept in a provisioned state. We can accomplish this with the Stop-AzureVM cmdlet.

Image of command output
  Using Stop-AzureVM with the StayProvisioned parameter

Now that our virtual machine is selected and in the right state, we can proceed to the next step of finding each virtual hard disk we want to back up and restore.

Identify virtual hard disks

Virtual machines in Windows Azure can be provisioned with two general types of virtual hard disks: operating system disks and data disks. Each virtual machine will have one operating system disk from which it boots and runs the operating system. In addition, each virtual machine can have one or more additional data disks on which program code and data files can be stored. To perform a complete virtual machine backup, we’ll need to locate all of the virtual hard disks that our virtual machine is currently using.

To store the location for the operating system disk, we can use the Get-AzureOSDisk cmdlet.

Image of command output
  Locating the virtual machine operating system disk with Get-AzureOSDisk

For any virtual hard disk that we want to back up or restore, the two property values in which we’ll be most interested are the DiskName and MediaLink values, which are shown in the following image. These values provide the information that we’ll need to properly back up and restore each virtual hard disk that is associated with a virtual machine.

Image of command output
  Common property values for a Windows Azure virtual hard disk

To store the location for all data disks, we can use the Get-AzureDataDisk cmdlet. Because virtual machines can be provisioned with multiple data disks, this cmdlet returns of a collection of data virtual hard disks.

Image of command output 
  Storing location for data disks with the Get-AzureDataDisk cmdlet

Create cloud storage container for storing backups

Prior to performing a backup, we’ll need to make sure that a container exists in our Windows Azure Storage Account to store these backup copies. First, we’ll need to determine the name of our Windows Azure Storage Account. We can do this by leveraging the MediaLink property of Azure Disks mentioned earlier.

Image of command output
  Determining the name of Windows Azure Storage Account by using MediaLink property

Now that we know the name of our Windows Azure Storage Account, we’ll want to set it as the current storage account for the remainder of our script by using the Set-AzureSubscription cmdlet.

Image of command output
  Setting the current storage account

Next, we can easily check to see if our desired container location for storing backups already exists inside our storage account, and if not, we can quickly create it by using the New-AzureStorageContainer cmdlet.

Image of command output
  Creating a new Windows Azure storage container

We can confirm that the new storage container has been created by using the Get-AzureStorageContainer cmdlet without parameters.

Image of command output
  Confirming creation of storage container with Get-AzureStorageContainer cmdlet

Now, we’re ready to back up our virtual machine!

Back up virtual machines in Windows Azure to cloud storage

To create a backup copy of the operating system disk on our virtual machine, we’ll first set the values for a couple variables that identify the blob and container names for the virtual disk that we want to back up. Then, we’ll use the Start-AzureStorageBlobCopy cmdlet to begin the copy process to our previously defined backup container location.

Image of command output
  Using Start-AzureStorageBlobCopy cmdlet to back up virtual hard disk

It’s important to note that the copy process performed by the Start-AzureStorageBlobCopy cmdlet is asynchronous in nature, and it runs in the background on the Windows Azure platform. To ensure that the copy process has completed before continuing with the next line in a script, we can use the Get-AzureStorageBlobCopyState cmdlet to wait until the copy process is finished.

Image of command output
  Using Get-AzureStorageBlobCopyState to confirm that the copy process completed

To back up our Windows Azure data disks, we’ll use a similar set of cmdlets, but we’ll run them inside a ForEach loop because Windows Azure data disks are returned as a collection.

Image of command output
  Back up data disks by using ForEach loop

After the backup process has completed, use the Get-AzureStorageBlob cmdlet to confirm that a copy of each virtual hard disk now exists in the backup storage container location.

Image of command output
  Using Get-AzureStorageBlob to confirm backup copies

Our backup process is complete, and we can now restart the Windows Azure virtual machine by using the Start-AzureVM cmdlet.

Image of command output
  Using Start-AzureVM to restart virtual machine after back up is complete

Congratulations! But keep learning!

You’ve completed the process for creating cloud backups of virtual machines in Windows Azure with Windows PowerShell! You can use the cmdlets and snippets in this post to quite easily build an automated approach to capture a backup of each Windows Azure virtual machine in your subscription, perhaps on a nightly basis.

In Part 2 of this series, we’ll walk through the process of restoring virtual machines in Windows Azure from these backups so that you can automate the complete end-to-end backup and restore process.

In addition, you may want to leverage these resources to continue your learning about Windows Azure Infrastructure Services:

Thank you, Keith, for sharing your time and knowledge.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Comments (19)

  1. Chen V says:

    Good Explanation!!!

  2. Good Article Thanks for sharing.

  3. Great post. Thank you.

  4. florian says:

    Hi Keith,

    Thank you for this precious memo.

    I am actually following your step by step. I also import my subscription to configure it by default but I couldn’t be able to create a New-AzureContainer.

    I got instead the following error:

    Get-AzureStorageContainer : Can not find your azure storage credential. Please set current storage account using
    “Set-AzureSubscription” or set the “AZURE_STORAGE_CONNECTION_STRING” environment variable.
    At line:1 char:7
    + if (!(Get-AzureStorageContainer -Name $backupContainerName -ErrorAction Silently …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-AzureStorageContainer], ArgumentException
    + FullyQualifiedErrorId : ArgumentException,Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet.GetAzureStorageCon

    If I try to get-Subscription I can actually see that I have my 2 subscriptions.

    Does anyone has an idea for helping me to fix my issue ?



  5. Bo says:

    Hi Keith,

    I’d like to see one improvement of the scripts. Because currently $vmOSBlobName is derived from $vmOSDisk.MediaLink.Segments[-1], next time when the backup scripts are run, we are prompted to overwrite the .vhd file in the backups container. So we can only
    keep one backup copy…

    I desire to backup multiple copies of the same .vhd file, of different timestamps, and be able to select one of the multiple copies to restore. Basically I want to be able to do the same thing as I have been doing with the GUI in Hyper-V.

  6. Ivan Neganov says:

    The ‘Get-AzureStorageContainer’ didn’t work for me either with the same error as Florian has reported. What works instead is these 2 commands:
    $context = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey

    New-AzureStorageContainer -name $backupContainerName -Permission Off -Context $context

    The comes from STORAGE >> >> MANAGE ACCESS KEYS in the Azure management UI. Didn’t try reading the key via script though – if this cannot be done I’d just stick it into a constant in the script. HTH

  7. Christian says:

    I want to be able to not shut down the VM as we are live and this would be utilized as a backup solution. Is there a way to not shutdown the VM?

  8. Ludovic Boggio says:

    Hello, Ed, and thank you for that article I used to schedule my backup on automation. But I met an issue I’m trying to figure with MS support team : the Start-AzureStorageBlobCopy cmdlet will not erase an existing file with the same name, even by using
    he "-force" switch. So, if you want to run that operation everiday days/weeks/whatever, you will meet an issue, and the command won’t eventually return any error (copystatus=success). I wanted to rename the previous copy, but PowerShell doesn’t provide any
    command to do so, and the option to delete previous copy before making a new one is a bit dangerous on a backup scenario.
    If anyone has an idea, I’d appreciate; if MS Support Team bring me one, I’ll try to think about sharing it here.

  9. Robert says:

    Question re permissions. I am trying to work out how to do this with a user that only has the ability to write (not read, delete or modify) blob data (like IAM in AWS). This would allow me to place the scripts on the machines themselves without fear of
    them overwriting historical snapshots if they became compromised. Any pointers ?

  10. ian_pick says:

    Scripting to get a snapshot, that’s just silly. In VMware it’s right-mouse-click > ‘take snapshot’

  11. Robert says:

    Did the Part 2 (how to restore) of this series ever come out? I’m looking into backup methods. Snapshots seemed easy, but I didn’t like the restore process, which involves overwriting the original disks. Making a copy of the disks via BlobCopy seems like
    a good idea, but I think I can skip a lot of the scripting with a single save-azurevmimage command, and it works even if the vm is still online.

    Of course, the hard part now is the restore. So far, my process is to create a new vm from an image backup, delete the new vm but keep the attached disk, and then attach the disk to another vm to recover files or to swap the place of the os or data disk.

  12. Aaron G says:

    I have a question on this – it is very helpful but I am not great with powershell and what I am looking to do is quite complex in my opinion.

    The Aim : automate a task to control the size of a VM in azure – the code is below, it is fully tested and also fully functional and it works fantastically. However, what I would like to do – before I do the step "Update-AzureVM" – is take a snapshot blob back-up
    of the VM.

    My plan is as follows :

    Change instance Size using below code (done)
    Stop VM
    Take backup to blob storage in Azure
    Start VM

    Can anyone help elaborate my code?? Please

    P.s. this is only one of the sizes for demo purposes.


    Select-AzureSubscription -SubscriptionName "Microsoft Azure Enterprise"

    Function HowTo-SetAzureVMSize{
    [string]$ServiceName = "",
    [string]$VMSize = "Large"
    Get-AzureVM –ServiceName $ServiceName –Name $Name |
    Set-AzureVMSize $VMSize |
    HowTo-SetAzureVMSize –ServiceName "" –VMSize "Large"


  13. Aaron G says:

    The above code lost it’s formatting upon posting, but you get the idea

  14. Kevin says:

    @Florian – I realise this is an old post, but it might help others with the same issue. You need to use Set-AzureSubscription to set your CurrentStorageAccountName for the current session, which you do like so:

    Set-AzureSubscription -SubscriptionName "My Subscription" -CurrentStorageAccountName "MyStorageAccountName"

    You should also, as a matter of good practice, use:

    Select-AzureSubscription -SubscriptionName "My Subscription"

    before doing that, so that you have a currently selected subscription too.



  15. Aaron G says:

    And idea on the backup of an Azure VM when shutting down automatically with script??



  16. alan says:


    If you add the -DestBlob arg to the Start-AzureStorageBlobCopy you are able to achieve exactly that.

    Start-AzureStorageBlobCopy -SrcContainer $vmOSContainerName -SrcBlob $vmOSBlobName -DestBlob "$(get-date -f MM-dd-yyyy-HH:mm) $vmOSBlobName" -DestContainer $backupContainerName

  17. De Jager says:

    Hi Keith

    Do you know of a Power shell script that can email a backup reports of Azure Backup vault?
    I want the same information that the Vault shows you on backup status but I can’t find a script anywhere !

  18. Nikolay P. says:

    For coping the HVD blob I would rather go this way:

    #Back up virtual machines in Windows Azure to cloud storage

    $OSUri = $VmOSDisk.MediaLink.AbsoluteUri
    Start-AzureStorageBlobCopy -srcUri $OSUri -DestBlob "$(Get-Date -f MM-dd-yyyy)_$($vmOSBlobName)" -DestContainer $backupContainerName

  19. De Jager Laubscher says:

    #After not finding a solution online I developed this script to create Azure Backup Vault Notifications via email
    #Just run it as a powershell script as a scheduled task on a server in your org and you will receive Azure Backupvault notifications and status reports in your inbox
    #Script by De Jager Laubscher revised by Theodore Seroadi

    Import-module Azure
    #Enter your Azure logon details below
    $MyAzureName = “”;
    $MyAzurePassword = ConvertTo-SecureString ‘YourPasswordHere’ -AsPlainText -Force;
    $AzureRMCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $MyAzureName, $MyAzurePassword
    Add-AzureRMAccount -Credential $AzureRMCredential
    Switch-AzureMode AzureResourceManager


    # Set the backup vault name and number of days you want to report Backups for
    $backupvaultname = “Name of your Azure Backup vault”
    $numberofdays = 2

    #Initialize variables
    $backupvault = Get-AzureRMBackupVault -Name $backupvaultname
    $enddate = ([datetime]::Today).AddDays(1)
    $startdate = ([datetime]::Today)

    #Enter the Email settings for your setup below
    $smtpServer = “IP Address of your SMTP Server”
    $smtpFrom = “”
    $smtpTo = “”
    $messageSubject = “Azure Backup Vault Report”
    $message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
    $message.Subject = $messageSubject
    $message.IsBodyHTML = $True

    for( $i = 1; $i -le $numberofdays; $i++ )
    # We query one day at a time because pulling 2 days of data might be too much
    $dailyjoblist = Get-AzureRMBackupJob -Vault $backupvault -From $startdate -To $enddate -Type AzureVM -Operation Backup
    Write-Progress -Activity “Getting job information for the last $numberofdays days” -Status “Day -$i” -PercentComplete ([int]([decimal]$i*100/$numberofdays))

    foreach( $job in $dailyjoblist )
    #Extract the information for the reports

    $message.Body =
    $newstatsobj = New-Object System.Object
    $newstatsobj | Add-Member -type NoteProperty -name Date -value $startdate
    $newstatsobj | Add-Member -type NoteProperty -name VMName -value $job.WorkloadName
    $newstatsobj | Add-Member -type NoteProperty -name Duration -value $job.Duration
    $newstatsobj | Add-Member -type NoteProperty -name Status -value $job.Status

    $details = Get-AzureRMBackupJobDetails -Job $job
    $newstatsobj | Add-Member -type NoteProperty -name BackupSize -value $details.Properties[“Backup Size”]
    $DAILYBACKUPSTATS += $newstatsobj

    $enddate = $enddate.AddDays(-1)
    $startdate = $startdate.AddDays(-1)

    #Sets the column
    $a = “”
    $a = $a + “BODY{background-color:white;}”
    $a = $a + “TABLE{border-width: 1px;border-style: solid;border-color: Purple;border-collapse: collapse;}”
    $a = $a + “TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:LightSeaGreen}”
    $a = $a + “TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:WhiteSmoke}”
    $a = $a + “”


    $message.Body = $DAILYBACKUPSTATS | ConvertTo-Html -Head $a
    $smtp = New-Object Net.Mail.SmtpClient($smtpServer)

Skip to main content