Azure RemoteApp Clean-up AD with Azure Automation


You can deploy Azure RemoteApp in different scenarios. One of the scenarios is a Hybrid Deployment. In a Hybrid deployment the Azure RemoteApp instances are added to your Active Directory. The instances will be added to a dedicated OU in that Active Directory. When you start working with a Hybrid Deployment you will notice after some time that the orphaned AD Computer objects of Azure RemoteApp instances will not be deleted. This blogpost will focus on using cleaning up this computer accounts with using a new Azure RemoteApp cmdlet and Azure Automation.

First we need to add a Hybrid Worker to our Azure Automation environment. This is needed because we want Azure Automation to execute cmdlets against our Local Active Directory. So first we need to add a hybrid worker, this is well described here. See below my command of adding a Hybrid Worker:

Note: No spaces are allowed in the ‘GroupName’. Otherwise you will receive the following error: Add-HybridRunbookWorker : One or more errors occurred.

Now you have your Hybrid Worker we can start configuring the Runbooks. I will use 2 runbooks for this solution:

  1. The main runbook will get the active Azure RemoteApp instances by using the cmdlet ‘Get-AzureRemoteAppVM’. This is a new cmdlet can be used to get the current in use Azure RemoteApp instances.
  2. The second runbook will be triggered from the main runbook and will first disable the orphaned objects and finally delete them based on the ouput of the above cmdlet.

Let’s now start with creating the components in Azure Automation.

  1. The first step is to check if the Hybrid Worker is added to your Azure Automation environment:

  2. The next step is to check if the needed Assets are in place. Click on ‘Assets’
  3. Click on Modules and check if the Azure Module is installed and have at least a version of 1.0.0. If the Azure module is not available you can add this from the PowerShell Gallery:

  4. The next step is to add the Azure Automation credentials needed for the Runbooks. You will have to add the following credentials:

    Azure_Subscription = Credentials which have access to your Azure Subscription (will be used to get the active Azure RemoteApp instances)

    LocalADCredentials = Credentials which will be used to perform the actions in the Active Directory, this account needs delete and disable Computer Objects rights

    Mail_credentials = These credentials will be used to send a result email.

  5. The next step is to create the CleanUp_LocalAD runbook of the type PowerShell

    When created click on Edit add the following code:

    param ( 
     # Mandatory parameter for the name of the Active Directory OU 
     # Mandatory parameter with the active RemoteApp VMS
    Import-Module ActiveDirectory
    #Load the Local Active Directory Admin Credentials
    $Local_Cred = Get-AutomationPSCredential -Name 'LocalADCredentials'
    $disabled_instances = @()
    $deleted_instances  = @()
    $active_instances   = @()
    foreach ($vm in $vms) {
      $active_instances += $vm.VirtualMachineName
    $ARAInstances = Get-ADComputer -Filter * -SearchBase $AD_OU_DN -Credential $Local_cred
    foreach($instance in $ARAInstances) {
      $Name = $instance.Name
      $check = $active_instances -contains $instance.Name 
      if( $check -eq $False) {
         if( $instance.Enabled -eq $true) {         
            Set-ADComputer $instance -Enabled $False -Credential $Local_cred
            Write-Output "Disabled : $name" 
         } else {
            $instance | Remove-ADObject -Recursive -Confirm:$False -Credential $Local_cred
            Write-Output "Deleted : $name" 

  6. The next step is to publish this Runbook, you can only use published runbook as a Child runbook
  7. Now it’s time to create the ‘main’ runbook to Azure Automation. This runbook is of the type PowerShell Workflow:

    When created click on Edit add the following code:

    workflow AzureRemoteApp_CleanUp_AD
     param ( 
        # Mandatory parameter for the name of the Active Directory OU 
       # Mandatory parameter for the name of the RemoteApp Collection
       # Mandatory parameter for the email address where the results will be send to
       # Mandatory parameter for the name of the Automation Account Name
    #Load the Azure Credentials
    $Cred = Get-AutomationPSCredential -Name 'Azure_Subscription'
    #Select the Azure Subscription and connect
    Add-AzureAccount -Credential $Cred
    Select-AzureSubscription -SubscriptionID '<ENTER AZURE SUBSCRIPTION ID>'
    #Get All active Azure RemoteApp instances
    $vms = Get-AzureRemoteAppVM -CollectionName $RA_Collection
    #Start the Child Runbook/PowerShell Script on the Hybrid Worker
    $params = @{"VMS"=[array]$vms;"AD_OU_DN"=$AD_OU_DN}
    $job    = Start-AzureAutomationRunbook –AutomationAccountName $AutomationAccountName –Name "CleanUp_LocalAD" –Parameters $params -Runon "< HYBRID WORKER GROUP>"
    #Check the progress of the Child Runbook
    $doLoop = $true
    While ($doLoop) {
      $job = Get-AzureAutomationJob –AutomationAccountName $AutomationAccountName -Id $job.Id
      $status = $job.Status
      $doLoop = (($status -ne "Completed") -and ($status -ne "Failed") -and ($status -ne "Suspended") -and ($status -ne "Stopped"))
    #Get the Ouput of the Childrunbook
    $output = Get-AzureAutomationJobOutput –AutomationAccountName $AutomationAccountName -Id $job.Id –Stream Output 
    if ( ($output.count -gt 0) ) {
       Write-Output "Mail send start"
      $MailCred   = "Mail_credentials"  
      $subject    = "Azure RemoteApp AD Cleanup" 
      $userid     = '<< Mail User ID>>'
      $Cred       = Get-AutomationPSCredential -Name $MailCred 
      $html = "<table><tr><td style='font-family:Arial; font-weight:bold;font-size:12px;'><b>AD CleanUp Results:</b><td></tr>"
      foreach ($row in $output) { 
         $html += "<tr><td style='font-family:Arial;font-size:11px;'>" + $row.text + "</td></tr>"
      $html += "</table><br />"
      $Body       = "<p style='font-family:Arial; font-weight:bold;font-size:11px;'>The following Azure RemoteApp AD Clean-Up changes are made:</p><br /> " + $html
      if ($Cred -eq $null) { 
         Write-Output "Credential entered: $MailCred does not exist in the automation service. Please create one `n"    
      } else { 
         $CredUsername = $Cred.UserName 
         $CredPassword = $Cred.GetNetworkCredential().Password 
         Send-MailMessage -To $Mail_Destination -Subject $subject -Body $Body -Port <PORT NUMBER> -SmtpServer '< MAILSERVER >' -From $userid -BodyAsHtml -Credential $Cred 

    Change the following values in the script:
    SubscriptionID : Enter the Subscription ID of your Azure Subscription
    RunOn: Enter here your Azure Automation Hybrid Worker Group Name
    UserID: Enter here a valid mail user ID from which the result email can be send
    SmtpServer: Enter here a valid Name of your Mail server
    Port: Enter here a valid port of your Mail server

  8. Now all components are added and you can start testing the main runbook. The Main runbook will start the CleanUp_LocalAD as a child runbook. The results of this runbook will be send in a mail to the entered mail destination.

This will result in a clean OU of the Azure RemoteApp instances:

And a result email with the changes made:

If you want to use a PowerShell script to remove the inactive Azure RemoteApp instances from your AD then Freek Berson (MVP) has created one. You can find his blogpost here.

The scripts can be download from the Technet Gallery:

  1. The Main Runbook:
  2. The AD CleanUp Script:

One final thanks to Ronny de Jong for providing his Azure RemoteApp subscription to test the solution!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.