Windows Virtual Desktop Host Pool Automation Part 3

Hello together,

it´s been already a few weeks since I´ve released my last article and a lot of great things happened – especially in terms of Autoscaling for our WVD HostPools!

Since last week I´ve been extensively working on a consolidated solution, which is easy to use and supports existing Spring Update Windows Virtual Desktop Host Pools and finally – here it is! This solution combines the best of Microsoft´s scripts, with user interfaces and one single script to rule them all 🙂

The WVDLogix Autoscaling Tool in Preview!

Download it from my GitHub Repo (info, you just need to download the Powershell):

To help you getting started with my script I´ve created a video for you which explains the steps in detail. Please find it here:

Really easy to use right? – Here you can find the detailed documentation


To start with the script the following prerequisites must be fulfilled:

  • Have an Azure Subscription and Tenant properly configured
  • Have a first Host Pool (the number of machine doesn´t matter)
  • Create a Resource Group upfront for your automation resources (to ensure proper separation from other resources)
  • Have the Az Powershell Modules installed

Next, you need to download the Powershell script from GitHub using the link above, or by clicking here.

I´ve stored the script in my preferred location, this is C:\WVD\Autoscaling in my example.

Once this is done, all you need to ensure is to start Powershell with elevated rights (Administrator). You can do this by right clicking on the Powershell icon from your startmenu and select “Run as Administrator”.

Now we´re going to navigate to the location were we´ve stored the script in. For me this is C:\wvd\Autoscaling so I switch the directory to it.

cd C:\wvd\Autoscaling

Now I can run the script by typing:


The first thing you need to do is to login to your Azure tenant with administrative permissions.

Now, the Autoscaling Tool will ask you to specify a download folder for the working files and scripts by Microsoft, which will be used to finalize the setup process. In my case I select the same folder, where my actual script is and hit enter.

You will see that three more scripts will be downloaded to your computer, let me explain their purpose and in the order they´re executed.

  1. CreateOrUpdateAzAutoAccount.ps1
    This one will create the Automation Account and Runbook in your environment and import all the required modules you need to run the Autoscaling
  2. New-RunAsAccount.ps1
    To run operations on the virtual machines it´s mandatory to have a “run-as account” in place. As this tool should give you a single place for all operations required, this tool will create this Account for you and provides you with everything you need.
  3. CreateOrUpdateAzLogicApp.ps1
    This script is going to create the Logic App in your environment and fills it with the parameters which fit best for your environment. You will see the parameters in detail when we continue.

To make it easy for new users with Powershell / WVD / or Azure in general, I´ve tried to built in as much graphical interfaces as I could (a real GUI will come in the next version).

But for now we can select a Resource Group to place our automation resources in:

This GridView will present you all RGs available in your tenant with your subscription. I select the one I´ve created upfront, which is called KCLD-WE-Automation and click “OK” on the lower right corner to continue.

Now I can select a location for my resources, this will be represented as GridView as well. Please select your option and hit the OK button.

If you want to benefit from gathered logs, you have the possibility to send all those logs to your LogAnalyticsWorkspace. The next question gives you the opportunity to type in the name of your LogAnalyticsWorkspace. This is an optional feature! Just leave it empty and hit enter to continue.

Now the tool is asking you for a secure password, which will be needed to sign the “run-as account”. Please provide a secure password here and hit enter.

And now the tool will create the Automation Account, Runbook and “run-as account” for your environment.

ATTENTION! This process can take between 15-20 minutes! There is no manual action needed in between.

In some cases, especially if you used this script already, it might be possible that you receive an error message at the level of “run-as account” creation. The tool will remediate this issue by itself while informing you that “New-AzRoleAssignment: The role assignment already exists”.

Once this process is done, we need to configure our LogicApp with some parameters, which need to be copied from a few lines above.

Please copy the WebHookURI, represented by the agent and mark it with your mouse and make a right click to copy it. Afterwards paste it in the field below:

The highlighted area represents the WebHookURI – make sure that there is no space in between

Next you need to specify a Tag to exclude resources from being up- and downscaled! This is a great solution in case you want to have a machine 24/7 up and running. You can define this Tag from the Azure Portal or Powershell and just type the value here. In my case I leave it as is and hit enter.

Now, a new window will open, which allows you to select your HostPool. If you have already multiple HostPools, select the one, which shall be automated. Currently there can only be one HostPool automated by the script at a time – you would need to run the script again to also manage another HostPool.

Now you will be prompted for the following parameters in a row. The I will explain each value in brackets!

  • Please fill out how often the job shall be repeated, values in minutes, e.g. ’15’ (defines the recurrence interval – can be changed later on)
  • Enter the start time for peak hours in local time, e.g. 9:00 (Defines when the automation should start)
  • Enter the end time for peak hours in local time, e.g. 18:00 (Defines when the automation should stop)
  • Enter the time difference between local time and UTC in hours, e.g. for CET: +2:00 (Defines the timezone, for CET it´s +2:00)
  • Enter the maximum number of sessions per CPU that will be used as a threshold to determine when new session host VMs need to be started during peak hours ( Defines the maximum number of sessions per CPU, to determine when new Session Hosts should be started)
  • Enter the minimum number of session host VMs to keep running during off-peak hours (Lets you define the resources, that you need to allow computing after the business hours)
  • Enter the number of seconds to wait before automatically signing out users. If set to 0, any session host VM that has user sessions, will be left untouched (Allows you to give users time before their sessions will be disconnected in case a downscaling occurs)
  • Enter the title of the message sent to the user before they are forced to sign out (The logoff message title)
  • Enter the body of the message sent to the user before they are forced to sign out (The logoff body message)

And finally, when everything has configured well, you will see the the logic app scheduler is successfully created.

And finally that´s it! The Autoscaling script has been successfully configured and is able to do it´s job.


In case, that some values aren´t correct or you just want to modify the scheduling / recurrence or any other value, you can run the script again, or navigate to the Azure Portal, into the resource group, where you´ve created all the automation resources and select the Logic App.

On the left-hand side select “Logic app designer”

And now you can see in the center of the screen all values that you are able to change, in case a modifcation is needed.

Click on save in the top left corner and your changes will be immediately active!

I really hope this helps you out there to get started with automation! At this stage, I also want to thank Microsoft for sharing the initial version of the script (Links can be found in the script), which has been modified and consolidated in my tool and which will be used by me to get extended functionalities.

I´m really looking forward to your feedback!



(Visited 70 times, 1 visits today)


  1. Pingback: WVD Weekly blog post 7th June 2020 - 14th June 2020 - WVD Community Website

  2. Pingback: Windows Virtual Desktop Host Pool Autoscaling –

  3. Leee June 16, 2020 at 4:18 pm

    Great presentation Patrick!

  4. Jeffrey Wolff June 19, 2020 at 6:07 pm

    Learned a lot in short amount of time. Thank you

  5. Jeffrey Wolff June 20, 2020 at 4:33 pm

    on your script i get the error “The ampersand (&) character is not allowed.”

  6. Jeffrey Wolff June 20, 2020 at 5:08 pm

    my bad i made a copy paste mistake

  7. Jamie June 29, 2020 at 6:55 pm


    This looks awesome. However it just seems to error
    “C:\WVDAuto\CreateOrUpdateAzAutoAccount.ps1 : Cannot validate argument on parameter ‘Name’. The argument is null or empty.”

    I’ve added the necessary details when prompted

    1. Patrick June 30, 2020 at 9:58 pm

      Dear Jamie,

      thanks a lot for your feedback. Please provide me with more detailed information or maybe a screenshot! I would really like to help you get it running.

  8. Pingback: UX Series – Windows 10 StartMenu optimization | WVDLOGIX - Windows Virtual Desktop and FSLogix Blog

  9. Ben Martin July 7, 2020 at 9:45 pm

    Hi Patrick,
    great guide and script! In case you are working with multiple subscriptions you can add:
    “Get-AzSubscription | Out-GridView -PassThru | Select-AzSubscription”
    to select the subscription at the beginning.

    Best regards

  10. Rohit July 13, 2020 at 12:04 pm

    I have used your script but I have a question. it seems that it is not stopping the VM’s if session count drops below threshold limit. VM’s should be stopping if there are no user session running? Correct.

  11. Rohit July 13, 2020 at 12:28 pm

    Basically looking at below details shouldn’t it be stopping VM’s?
    2020-07-13 15:56:02 [434] Number of session hosts in the HostPool: 2

    2020-07-13 15:56:02 [456] Using current time: 2020-07-13 15:56:02, begin peak time: 2020-07-13 08:00:00, end peak time: 2020-07-13 18:00:00

    2020-07-13 15:56:02 [460] In peak hours

    2020-07-13 15:56:02 [489] Get all VMs, check session host status and get usage info

    2020-07-13 15:56:04 [510] Session host: ‘’, power state: ‘VM running’, status: ‘Available’, update state: ‘Succeeded’, sessions: 0, allow new session: True

    2020-07-13 15:56:04 [513] Get all VM sizes in location: eastus

    2020-07-13 15:56:05 [510] Session host: ‘’, power state: ‘VM running’, status: ‘Available’, update state: ‘Succeeded’, sessions: 0, allow new session: True

    2020-07-13 15:56:05 [560] Number of running session hosts: 2 of total 2

    2020-07-13 15:56:05 [561] Number of user sessions: 0 of total allowed 4

    2020-07-13 15:56:05 [562] Number of user sessions per Core: 0, threshold: 2

    2020-07-13 15:56:05 [563] Minimum number of running session hosts required: 0

    2020-07-13 15:56:05 [676] No need to start/stop any session hosts

    2020-07-13 15:56:05 [677] End

  12. nigel webster July 13, 2020 at 1:34 pm

    Hi Patrick. Great additions to the script. can I ask does this deployment now work with ARM deployments? W have recently redeployed our clients to the new ARM version and are awaiting updates from microsoft to be able to use the same shutdown scripts in this new environment.

  13. Brendan July 23, 2020 at 6:45 pm

    Enter the maximum number of sessions per CPU: Are you able to enter a fractional number? My use case for WVD is with MS Teams which is very CPU intensive. I’m looking at something like .31 users per VM because I’m using a 16 core VM and want a max of around 5 users.

  14. Patrick Brechbiehl August 20, 2020 at 9:26 am

    Hi Patrick,
    Thanks for your work. In my client’s tennant it is working.
    However, I noticed that the script is taking the VM’s size from the template that was provided when the session hosts were deployed.
    And after I deployed the session hosts, I changed their size, but the script is not aware of that, and therefore this is impacting the way the SessionThresholdPerCPU is working.
    Is there a way to get the size of the VM dynamically?

    Best regards

    1. Patrick September 22, 2020 at 2:29 pm

      Hi Patrick,

      thanks for your feedback!
      Regarding the VM size, this is a point not addressed in the automation yet.
      But I noted it for the third version of the tool.

      In the meantime I recommend to use the latest version of the tool available here:

      If you have any question, please let me know!
      Always happy to help!

  15. Roel Vliegen November 4, 2020 at 4:33 pm

    As Ben Martin already said: the script isn’t ptoperly functioning when havinf multiple subscriptions.
    Commenting line 37 in the script and adding the following 2 lines will present you a subscription selection grid en pass thru the selected subscription ID.

    $Subscription = Get-AzSubscription | Out-GridView -OutputMode:Single -Title “Select your Azure Subscription”
    Select-AzSubscription -Subscription $Subscription.Id

  16. Nitin July 11, 2021 at 3:53 pm

    Use Citrix to deliver WVD to make this 1000x easy. This article is great but too much scripting is prone to Human Error and Inefficient use of time


Leave A Comment

Your email address will not be published. Required fields are marked *