Azure Site Recovery

This script is intended to be run as part of a Azure Site Recovery recovery plan post-steps routine script. It will run a script locally on all Azure VMs in a recovery group using the Run Command functionality. This is helpful if you need to change any OS configurations needed for the failover VM to function correctly in a new Azure Region, such as an application configuration needing the updated IP address of the VM. It requires the module “ThreadJob” from the PowerShell Gallery.


#requires -Modules ThreadJob

#region BoilerplateAuthentication
#This requires a RunAs account
$ServicePrincipalConnection = Get-AutomationConnection -Name ‘AzureRunAsConnection’

Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $ServicePrincipalConnection.TenantId `
-ApplicationId $ServicePrincipalConnection.ApplicationId `
-CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint

$AzureContext = Select-AzureRmSubscription -SubscriptionId $ServicePrincipalConnection.SubscriptionID
#endregion BoilerplateAuthentication

#The script you wish to run on each VM
$scriptBlock = @”
Get-Date | Add-Content -Path “C:\MyConfig\MyConfigFile.txt”
$scriptPath = “updateConfig.ps1”
#The cmdlet only accepts a file, so temporarily write the script to disk using runID as a unique name
Out-File -FilePath $scriptPath -InputObject $scriptBlock
$scriptFile = get-item $scriptpath
$fullPath = $scriptfile.fullname

$jobIDs= New-Object System.Collections.Generic.List[System.Object]

#Get ASR Recovery Plan Context VM Map
$VMinfo = $RecoveryPlanContext.VmMap | Get-Member | Where-Object MemberType -EQ NoteProperty | select -ExpandProperty Name
$vmMap = $RecoveryPlanContext.VmMap

#Start script on each machine
ForEach($VMID in $VMinfo)
$VM = $vmMap.$VMID
if( !(($VM -eq $Null) -Or ($VM.ResourceGroupName -eq $Null) -Or ($VM.RoleName -eq $Null))) {
#this check is to ensure that we skip when some data is not available else it will fail
Write-Output “Resource group name “, $VM.ResourceGroupName
Write-Output “Rolename “, $VM.RoleName
Write-Output “Subscription Id “, $VM.SubscriptionId
Write-Output “Script full path “, $fullPath
$mute = Select-AzureRmSubscription -Subscription $VM.SubscriptionId
Write-Output “Invoking command on ‘$($VM.RoleName)’ …”
$newJob = Start-ThreadJob -ScriptBlock { param($resourceGroup, $vmName, $scriptPath) Invoke-AzureRmVMRunCommand -ResourceGroupName $resourceGroup -Name $VmName -CommandId ‘RunPowerShellScript’ -ScriptPath $scriptPath} -ArgumentList $VM.ResourceGroupName, $VM.RoleName, $fullPath

$jobsList = $jobIDs.ToArray()
if ($jobsList)
Write-Output “Waiting for machines to finish executing…”
Wait-Job -Id $jobsList

foreach($id in $jobsList)
$job = Get-Job -Id $id
if ($job.Error)
Write-Output $job.Error


#Clean up our variables:
Remove-Item -Path “updateConfig.ps1”

Write-Output “Script Completed.”

Be the first to comment

Leave a Reply

Your email address will not be published.