(Exactly) 200 Crappy Words on Cross-Forest AD-Joined Azure File Shares

In a client deployment recently we leveraged Azure Files, joined to a Domain in the client’s primary AD Forest. AVD Sessions are established from other Domains and Forests and all was well with the world – until we needed to deploy security baselines for compliance. After introducing the locked-down configuration, we were no longer able to authenticate AzFiles across AD Forests, and User GPO processing was failing. 

Part of the CIS L1 benchmark is to disable any authentication encryption except AES128/256 and “future” methods… – When handling authentication cross-Forest, this authentication method is not supported, even if the storage account has been properly configured for AES256 encryption. It appears this authentication will work only using the RC4 encryption method. – This also affects the ability to process User Policy if this is linked to the other Forest using the Loopback policy option to enable cross-Forest processing User Policies. 

The real fun was in the troubleshooting and investigation; Once the policy has been applied (GPO > Security > Local Policies), it seems to “tattoo” the machine, so that even when the policy is removed, the session host won’t climb down from the elevated security stance. – The session host must be recreated. 

After Action Report: AVD Azure AD Join Checklist in 200 Crappy Words

Preface: Why only 200 crappy words?

I’m seeing a growing number of AVD deployments going AAD-only thus decoupling from the technical debt of legacy Active Directory, and in many cases opting for Intune over on-premises SCCM etc for device management.

Thankfully Microsoft makes the process of deploying AAD-only AVD session hosts pretty straightforward, however, the below calls out a few lessons from the field to be mindful of….

  1. Microsoft only supports a limited number of use cases for AAD-joined VMs
  2. There are additional RBAC roles (Virtual Machine User Login and Virtual Machine Administrator User Login) to be considered for AAD joined VMs, correct placement of these roles is key to ensuring ease of management at scale
  3. If the device a user is connecting to an AAD joined AVD VM from is not joined to the same Azure AD as AVD, add targetisaadjoined:i:1 as a custom RDP property to the host pool
  4. If you’re deploying Windows 10 version 1511 or earlier you’ll need to enable the PKU2U protocol, this is enabled by default in version 1607 or later
  5. When configuring Conditional Access for AAD joined AVD, disable legacy per-user MFA and exclude the Azure Windows VM Sign-In app
Word Count: 196

Enrolling Terraform Deployed AVD Session Hosts into Intune

Background / Requirements:

This post will describe the recent problem my team faced with enrolling Terraform deployed AVD session hosts into Intune.

Below is a summary of the high-level requirements for the wider AVD deployment.

  • Deploying AVD programmatically using Terraform through Azure DevOps Pipelines
  • Personal host pool only
  • All session hosts deployed directly from an Azure Marketplace Windows 10 Multisesson image (no custom images)
  • All session hosts are to be Azure AD joined only
  • All session hosts are to be enrolled in Intune for MDM (including app deployment)


The deployed session hosts would join Azure AD without issues, however, would not enrol in Intune.


The solution was simple in hindsight, however, admittedly took some head-scratching to get there.

To get to the solution we deployed a session host manually from the Azure portal and compared the resultant JSON from the Overview pane of the virtual machine, see below, to that of a session host deployed using Terraform.

In comparing the JSON output we found that the VM Extension used for the AAD Login for Windows had an additional setting block defined for MDM.

We updated the Terraform code block for the same VM Extension to include the missing settings block and deployed the session hosts, thankfully each session host auto-enrolled in Intune!

resource "azurerm_virtual_machine_extension" "AADLoginForWindows" {
    depends_on  = [
  name                 = "AADLoginForWindows"
  virtual_machine_id   = azurerm_windows_virtual_machine.vm.id
  publisher            = "Microsoft.Azure.ActiveDirectory"
  type                 = "AADLoginForWindows"
  type_handler_version = "1.0"
  auto_upgrade_minor_version = true

  settings = <<SETTINGS
        "mdmId" : "0000000a-0000-0000-c000-000000000000"

Notable thanks to Chris Aitken, my AVD and DevOps SME for his efforts, and the hours sitting on Teams calls to get this fixed!

If you have any queries or questions, please reach out on Twitter or LinkedIn.


WVD > Outlook running on Windows 10 Multi-Session displays “Need Password”

This post describes an issue that under certain circumstances can affect MS Outlook running on Windows 10 Multi-Session.

The issue manifests itself as MS Outlook constantly prompting the user for credentials, and even after entering their correct username and password the prompt constantly loops which to a user this gives the same experience as if they’d entered a wrong password.

Note, this was not all users, on every WVD session host, all of the time, it was certain users, intermittently, on differing hosts.


I too did the usual dance of looking to diagnose issues with the user’s credentials, such as changing the password, forcing AD Connect syncs, checking issues with Basic versus Modern Auth, AAD App Passwords, disabling MFA – nothing worked.

Just to set the scene and give a bit more background info this particular customer uses ADFS to proxy authentication from Azure AD to Active Directory, they use Windows 10 Multi-Session (Build 1909) and MS Office 365 (Build 2004).

I read through dozens of articles with one consistent theme of disabling the use of Web Account Manager – the below paragraph from Duo Support added great context:

“By default, Microsoft Office 365 ProPlus (2016 version) uses Azure Active Directory Authentication Library (ADAL) framework-based authentication. Starting in build 16.0.7967, Office uses Web Account Manager (WAM) for sign-in workflows on Windows builds that are later than 15000 (Windows 10, version 1703, build 15063.138). There are generally two problems we see WAM causing:

Users unable to authenticate (particularly after a password reset)

WAM introduces new requirements for Identity Providers (IdP) used to federate Office 365 (O365) logins. When a Windows 10 workstation is joined to an on-premise Active Directory, WAM/O365 requires the IdP to support the WS-Trust protocol.  When a user’s access/refresh tokens become invalid, such as after a password reset, the WAM framework tries to re-authenticate the user. The expected end-user experience is a popup window showing the login page of the IdP asking the user to re-authenticate. When the IdP is the DAG, this process will fail causing the user to be unable to re-connect to O365 with applications such as Microsoft Outlook. The user will see the authentication window open briefly then immediately close while Outlook continues to show the message Need Password.”

The article suggests disabling WAM using the below registry key:

Create Dword Value DISABLEAADWAM
Set a value of 1

Now, this did resolve the issue however I always felt it was a workaround and not a fix as I was mindful of the effect disabling this service had on other dependent applications and Windows services.

That’s when a colleague shared this post from Pieter Wegleven, WVD Product Manager at Microsoft.

Pieter’s post states that the issue could be caused when session hosts are registered in the same Azure AD tenancy as they are domain-joined, that is, domain joined to the same AD that syncs to the AAD in which they are registered – this is caused when a user selects the “use this account everywhere” prompt from an Office app which can be done by standard (non-admin) users.

I checked this in the customer’s AAD (Azure Portal > Azure Active Directory > Devices) which found that to be the case, see below.  Note how a single session host VM is registered multiple times with different owners, subsequently these are all the same users who initially reported the issue with Outlook.


Pieter’s post advises Microsoft are “making changes to the Windows 10 multi-session image in the Azure gallery to prevent users from registering VMs” however in the immediate time suggests two methods to resolve this issue.

First, and the Microsoft preferred method is to configure Hybrid AAD which would allow VM’s to be joined to AAD, rather than registered.

Below is a quick reminder on the differences between an AAD registered device versus joined.

Azure AD Registered > Devices that are Azure AD registered are typically personally owned or mobile devices, and are signed in with a personal Microsoft account or another local account.

Azure AD Joined > Devices that are Azure AD joined are owned by an organisation, and are signed in with an Azure AD account belonging to that organisation.

The second option is to prevent the VM from registering in Azure AD, this is the option I opted for on this occasion, namely because shifting to a hybrid Azure AD was a significant design decision and presented a change in architecture for the customer, and not something they would opt into quickly, nor should they.

Preventing VM’s from registering in Azure AD can be achieved by adding the below registry key:

Create Dword Value BlockAADWorkplaceJoin
Set a value of 1

Note, you could add the above registry key to existing machines that had previously registered in AAD, you would simply have to delete them from AAD.

I hope you found this post useful, if you’re interested in engaging more with others using and learning more about WVD please consider following the WVD Community on Twitter and joining the Slack channel, both ran by Neil and Stefan, and both great sources of info!


Troubleshooting connectivity from the RD Client to WVD Part 2 – Log Analytics

A few weeks ago I introduced an issue I was working on with a customer who was reporting intermittent issues connecting to Windows Virtual Desktop from the RD Client on their corporate devices, you can read that initial post here.

The focus of that post was doing some preliminary checks, namely comparing connectivity from the RD Client against the Web Interface at the time the user was reporting the issue, this would help narrow down whether the problem was environmental, as in, within the boundary of the users’ device, the customer VPN etc as a successful connection from the web interface would go some way to proving the health of WVD control plane, host pool and session host.

A quick recap on activities and results since that initial post…

Tests confirmed that the user could indeed connect using the web interface at the exact same time the RD Client would not connect, note the user in question was no longer working from home at the time, he was in the corporate office connected to their LAN.

Also note that at the time the user could not connect I confirmed that other users were connected to the same WVD resource, and I myself could connect using the RD Client.

We then worked with the customers’ network and security engineer (who maintains their Cisco Umbrella deployment) to systematically walk through the network topology to ensure traffic from that source IP was successfully traversing each node without error.

We also used WireShark to capture traffic from the users’ device, however, I’ll save that particular deep-dive for a follow-up post as I’m still analysing the results. What I’m hoping to do is compare the resultant capture with the WVD connectivity flow (from part 1) and correlate each step to a particular selection of the capture to hopefully show which step is having problems – this is still work in progress.

The below is an example WireShark capture I used with the customer as a comparison, I started the capture and then opened the RD Client, as mentioned in part 1 the RD Client will always refresh your subscriptions on start-up, this is shown from line 203 to 205 in which the initial connection is made after the RDWEB.WVD.MICROSOFT.COM hostname is resolved in DNS, from line 206 a secure connection is initiated to the WVD control plane which validates the TLS certificate against the GlobalSign certificate authority at line 217 to 221, this is one of the reasons internet access is required for WVD as the certificate authority is accessed from its public endpoint.


I’m hoping to have this analysis and deep-dive completed soon, I’ll document it in a follow-up post after I’ve had it reviewed for and verified for accuracy by the WVD Community and Microsoft WVD Global Black Belts.


Back to the troubleshooting…

Frustratingly during the analysis of traffic logs on the customers’ perimeter firewall and having made zero changes the RD Client was then able to connect to WVD!

This now has us, me and the customers tech team, scratching our heads – are we now looking for something dynamic in an otherwise static local architecture that under certain conditions cause these connectivity problems, such as asymmetric routing? Again, more on that in a later post as I’m working with the customer and their other supporting partners to build a diagram of their holistic network architecture.

After a productive conversation with the customers’ aligned Microsoft DSE it was agreed that whilst we wait for the issue to reoccur we would configure the WVD tenant to send logs to an Azure Log Analytics workspace to see if that could shed any light on the situation.

Setting up a new Log Analytics Workspace is very straight forward, from the search bar in the Azure Portal enter Log Analytics, from the results select Log Analytics Workspaces.


Select Add.


Select an appropriate Subscription and Resource Group, then provide a suitable name for the Workspace and a region to host it, ideally use the same region as the WVD session hosts are deployed.


Click ‘Next: Pricing Tier’ to proceed.

Select a pricing tier, details on pricing tiers can be found here.


Proceed through the next two options entering appropriate tags and finally review and create to create the Log Analytics workspace.

Once created the Log Analytics workspace will display a Workspace ID, note this down as you’ll need it later.

Note, the next steps to connect the WVD tenant apply to the Fall 2019 release only, the setup for Spring 2020 release differs.

Binding your WVD tenant quick and straight forward following this Microsoft article.

Before you start you’ll need the below info:

* WVD tenant name
* Azure subscription ID
* Log Analytics Workspace ID (available from Overview pane on the workspace itself)
* Log Analytics Primary Key (available from Advanced Settings > Connected Sources)

Once you have the above open PowerShell and run the below commands:

Add-RdsAccount -DeploymentUrl https://rdbroker.wvd.microsoft.com
Set-RdsTenant -Name  -AzureSubscriptionId  -LogAnalyticsWorkspaceId  -LogAnalyticsPrimaryKey

This will bind your WVD tenant to the Log Analytics workspace.

Be aware it can take up to an hour before log data will start to appear so be patient.

Note, connecting the WVD tenant to the Log Analytics Workspace will send log data at the tenant only, such as user-driven connection events, it will not send VM or guest OS performance stats, for that you must install the Windows Agent on the VM following this article.

WVD creates the three below custom logs in the workspace.


Like any log managment solution the key is often knowing what you’re looking for and how to find it, Log Analytics is no different, Microsoft provides two great example queries to get you started, here.

To query the workspace select Logs under General, this will open a new pane for the query editor.

I adapted one Microsoft’s example queries to show just failed connections from the RD Client where ClientType_s == “com.microsoft.rdc.windows.msrdc.x64” denotes connections from the RD Client, see below:


| where Type_s == "Connection"

| where Outcome_s == "Failure"

| where ClientType_s == "com.microsoft.rdc.windows.msrdc.x64"

| join kind=leftouter



| summarize Errors = makelist(pack('Time', Time_t, 'Code', ErrorCode_s , 'CodeSymbolic', ErrorCodeSymbolic_s, 'Message', ErrorMessage_s, 'ReportedBy', ReportedBy_s , 'Internal', ErrorInternal_s )) by ActivityId_g


on $left.Id_g  == $right.ActivityId_g

| join  kind=leftouter



| summarize Checkpoints = makelist(pack('Time', Time_t, 'ReportedBy', ReportedBy_s, 'Name', Name_s, 'Parameters', Parameters_s) ) by ActivityId_g


on $left.Id_g  == $right.ActivityId_g

|project-away ActivityId_g, ActivityId_g1

Select a time range, highlight the entire query (Control+A) and click Run.

The results will be displayed as below, this shows two failed attempts from the RD Client in the past 24 hours, this also shows the user is running Windows 10 build 1809 (11763) and version 1.2.945.0 of the RD Client – both extremely useful pieces of the information when analysing data and looking for trends.


Drilling down into each of those failed connections though is where the gold is!

From the left-most side of each log is an arrow to expand, the first tier provides a summary of the connection.


Afterwhich is a subset of the log displaying any errors, you can see from the below that this session failed with error code 2055, SSL_ERR_LOGON_FAILURE.

Now, I’m not going to profess to know exactly what that particular error is caused by but it is certainly enough to either focus and further troubleshooting or raise a support request with Microsoft.


Lastly, the final hive in the log in extremely interesting in that it walks you through the checkpoints of the connection flow, you can view the result of each checkpoint.


If you’re interested in engaging more with others using and learning more about WVD please consider following the WVD Community on Twitter and joining the Slack channel, both ran by Neil and Stefan, and both great sources of info!


Troubleshooting connectivity from the RD Client to WVD Part 1 – Getting Started

This week I’ve been working with a customer that is experiencing intermittent issues connecting into Windows Virtual Desktop from the RD Client installed on their corporate Windows 10 devices and was asked to formulate a list of troubleshooting steps that their IT team could follow to help find and resolve the root cause.

I reached out to Jim Moyle, our aligned WVD Global Black Belt for his thoughts, and in this post, I want to share those initial troubleshooting steps, along with the rationale for each, put them out to the wider WVD community for feedback and over the coming weeks update this article with the identified root cause and the steps taken to resolve the issue.

For info and early clarification, this customer is using the Fall 2019 release of Windows Virtual Desktop.

So, what is the problem?

As introduced, the customer is reporting that certain users, not all, are intermittently unable to connect to their WVD resource using the RD Client installed on their corporate Windows 10 device, furthermore, they never receive any errors (such as resources not available) nor have they indicated that the connection attempt times out (I’ll double-check this and update if required), it simply doesn’t connect.

The below screenshot was provided by an affected user, this shows the RD Client attempting to connect to a selected remote desktop.


Before delving any deeper and starting to define the tests to be undertaken lets quickly recap on how a user connects to WVD, that way once we do start defining a particular test we better understand the rationale behind it, that is, what are we trying to prove or disprove.

The diagram below shows the WVD connection flow.


Step 1 > The user launches the RD Client which connects to Azure AD, user signs in, and Azure AD returns token.
Step 2 > The RD Client uses the previously generated token and authenticates to Web Access, the Broker then queries the database to determine the resources (Remote Apps and Desktops) that the user is assigned to.
Step 3 > The user selects a resource (Remote App or Desktop) and the RD Client connects to the Gateway.
Step 4 > Finally, the Broker orchestrates the connection from the WVD instance (the Azure VM) to the Gateway (aka Reverse Connect).

Note, on start-up the RD Client will always refresh your feed, as below, this is the RD Client running through steps 1 and 2 in the above connection flow.


Now, let’s quickly cover some basic assumptions before we get into the testing, again I’ll update these as I speak with the customer IT team and understand more of the nuances of the issue.

Assumption 1 > WVD is a global service, as such, for resilience, it operates many instances of the WVD control plane (the backend services, such as Web Access, Broker and Gateway shown in the connection flow diagram) in each region, however, based on availability at the time the control plane managing your user’s connections into WVD may not be running in the same region as the WVD VM’s themselves. Azure use their Front Door (and Traffic Manager) service to provide a resilient and optimised connection to the control plane – let’s assume a control plane is always up and available.

However, if we wanted to clarify the control plane you’re using is healthy we could use the below Powershell commands.

# Import Fall 2019 WVD module
Import-Module -Name Microsoft.RDInfra.RDPowerShell

# Connect to WVD
Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com"

# Get control plane info
Invoke-RestMethod -Uri "https://rdweb.wvd.microsoft.com/api/health"

The below shows the results of the script, note the service is reporting as healthy and more importantly the Region URL shows that actual control plane you’re using.


Assumption 2 > This is only affecting certain users, other users can successfully connect to the same WVD resource at the same time others cannot indicating that the WVD VM’s themselves are healthy.

Again, if we want to verify the health of the WVD session hosts within a given host pool we could use the below Powershell commands.

# Import Fall 2019 WVD module
Import-Module -Name Microsoft.RDInfra.RDPowerShell

# Connect to WVD
Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com"

# Set Session Host Status
Get-RdsSessionHost -TenantName WVD-Tenant-Name -HostPoolName WVD-Host-Pool-Name | Select SessionHostName, Status

The results will be shown as below.


Assumption 3 > This is only affecting users on their corporate devices, I’ll double-check this with the customer IT team and update if needed.

Assumption 4 > The customer has all the WVD backend services opened and available through the corporate firewall and web proxies.  I know they use Cisco Umbrella for web proxy services, so something to be mindful of.

Assumption 5 > The user sees the same issue if they are on their corporate LAN, VPN or connected to the open internet from their home broadband as the majority of their staff are working from home.

So, what tests are we going to run when a user reports they cannot connect and why?

Test 1 > Can the user access the same WVD resource from the HTML5 interface at https://aka.ms/wvdweb?

Why? We need to narrow down whether the issues is only with the connection initiated from the RD Client, testing from the WVD Web Interface should help prove this.  If the user is able to authenticate to the web interface, see all of their assigned WVD resources and then successfully logon to a desktop it proves the issue is not with the control plane, their assignment or WVD session host.

Test 2 > Can the user resolve the WVD Global URL in DNS?

Why?  I’m almost certain that whatever the route cause is it will be environmental, that is, something occurring at that exact time on that device that is hindering the connection attempt. This is a very simple test to ensure that the device is able to resolve the WVD Global URL that is used to forward to the regional control plane instance and initiate the connections.

C:\Users\DeanLawrence>nslookup rdweb.wvd.microsoft.com
Server:  SkyRouter.Home

Non-authoritative answer:
Name:    waws-prod-db3-3dec2181.cloudapp.net
Aliases:  rdweb.wvd.microsoft.com

We could build on that test slightly using the Test-NetConnection cmdlet to test connectivity to the Regional URL (from test 2) over HTTP.

PS C:\Users\DeanLawrence> Test-NetConnection rdweb-neu-r1.wvd.microsoft.com -CommonTCPPort HTTP -InformationLevel Detailed

ComputerName : rdweb-neu-r1.wvd.microsoft.com
RemoteAddress :
RemotePort : 80
NameResolutionResults :
MatchingIPsecRules : 
NetworkIsolationContext : Internet
IsAdmin : False
InterfaceAlias : WiFi
SourceAddress :
NetRoute (NextHop) :
TcpTestSucceeded : True

Test 3 > Clear RD Client Subscriptions and Re-Subscribe

Why? As mentioned earlier, on start-up the RD Client performed a refresh of the feed, this then caches the subscription details in the registry.  This test is looking at whether there could potentially be an issue either with the cached settings or the authentication token. You can unsubscribe from the RD Client itself by clicking the 3 dot menu next to the tenant name and selecting Unsubscribe or running the below from a command prompt.

msrdcw.exe /reset /f

Well, that’s it for now (16/05/20), if you have any suggestions please send them my way on Twitter, I’ll update this post as soon as I’ve had a chance to work with the customers IT team and investigate these issues closer.


Part 2 in this blog series is up now, click here.

QuickFix > Starting and Stopping Azure VM’s using a Powershell Menu

This is another quick fix to help automate a somewhat monotonous task, this time it’s using Powershell to build a simple menu to give the ability to start and stop a set of Azure virtual machines using a Service Principal.

The script is pretty straight forward and can be easily adapted to add additional VM’s should you need to power up, or down, a larger set of virtual machines.

For ease and to keep this as hands-off as possible this script uses a Service Principal to authenticate to Azure AD and perform the task setting the VM power state, this saves having to manually enter credentials and responding to MFA challenges.
I’ve borrowed and adapted the Powershell commands directly from this Microsoft Windows Virtual Desktop article which can be used to create a Service Principal if you don’t have one created already.
# This script creates a Service Principal within Azure AD

# Install and import AzureAD PS Module
Install-Module AzureAD
Install-Module AzureAD
# Connect to Azure AD with a Global Admin account.
$aadContext = Connect-AzureAD

# Create Service Principal
$svcPrincipal = New-AzureADApplication -AvailableToOtherTenants $true -DisplayName "VM Power Menu Service Principal"

# Get Service Principal ID and Key 
$svcPrincipalCreds = New-AzureADApplicationPasswordCredential -ObjectId $svcPrincipal.ObjectId

# Return Service Principal App ID

# Return Service Principal Secret Key

# Return Azure AD Tenant ID

Before proceeding please ensure that the newly created Service Principal has the adequate permissions to start and stop the required virtual machines, this can be set directly on the VM’s themselves or on the Resource Group.

Note, if you’re setting these permissions in a production environment or an environment that is particularly security-sensitive please be mindful of the principle of least privileges, that is, avoid using elevated roles such as Owner or Contributor role if a lesser role would suffice, such as Virtual Machine Contributor.

Once the Service Principal has been created copy and paste the below into your code editor of choice, you will need to set the initial variables in the header, you can use the resultant output from the script above for the Azure AD Tenant ID  and Service Principal details.  You will also need to populate the two Azure VM variables and the associated hosting Resource Group.

Import-Module Az.Compute

$AADTenant = [Azure-AD-Tenant-ID-Here]
$SPAppID = [Service-Principal-App-ID]
$SPAppSecret = [Service-Principal-Secret-Key-Here]
$WVDVM1 = [Second-VM-To Start]
$WVVM2 = [Second-VM-To Start]
$AzRG = [Resource-Group-Hosting-VMs-Here]
$passwd = ConvertTo-SecureString $SPAppSecret -AsPlainText -Force
$pscredential = New-Object System.Management.Automation.PSCredential('$SPAppID', $passwd)

Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $AADTenant

function Show-Menu
     param (
           [string]$Title = 'Start-Stop WVD Lab'
     Write-Host "================ $Title ================"
     Write-Host "1: Press '1' to start WVD."
     Write-Host "2: Press '2' to stop WVD."
     Write-Host "Q: Press 'Q' to quit."
     $input = Read-Host "Please make a selection"
     switch ($input)
           '1' {
                'Starting WVD'
                    Start-AzVM -Name $WVDVM1 -ResourceGroupName $AzRG
                    Start-AzVM -Name $WVDWM2 -ResourceGroupName $AzRG
           } '2' {
                'Stopping WVD'
                    Stop-AzVM -Name $WVDVM1 -ResourceGroupName $AzRG -Force
                    Stop-AzVM -Name $WVDWM2 -ResourceGroupName $AzRG -Force
           } 'q' {
until ($input -eq 'q')

When executed the script presents a simple menu with 3 choices as below.


Note, after executing either options 1 or 2 the script will intentionally not exit and close, instead, it will await a response of Q to quit – this was done intentionally as a gentle reminder to the user to stop the VM’s they’d originally started.

Lastly, as a matter of good practice, for lab environments that don’t need to spin around the clock, for subscriptions that use free credit, or you’re just trying to keep costs down I’d always recommend setting an Auto-Shutdown time on non-production VM’s as a backup.

QuickFix > Set Working Directory on WVD RemoteApp

This one might be old news to some but I thought I’d share it as it got me out of jam earlier this week.

I needed to create a RemoteApp in WVD (Spring Release) for a proof of concept I was working on, however, this application required a working directory to be set for it to launch correctly.

I’ll stress this was a quick fix and there may be a more elegant way to achieve the same result but I was against the clock at the time.

The quick fix was to create a batch file locally on the WVD instance with the below syntax:

start /d c:\App-Working-Directory-Here c:\Executable-To-Launch-Here.exe


start /d c:\EstGrp\CM\830\CM\USER c:\EstGrp\CM\BINW\cmw32.exe

Once the batch file is saved, from the WVD Management UI create a new RemoteApp in the relevant Application Group and enter the path the batch file in the Application Path, continue to enter the Display Name and set the Icon Path to the path to the executable as normal:


As expected when you launch the application from the RD Client or WVD Web Interface (from the correct URL, thanks to Tom and Marcel 🙂 the batch file will launch, albeit quickly and then launch the required app.

Note, the same could be achieved using PowerShell with the below syntax:

Start-Process -FilePath C:\EstGrp\CM\BINW\cmw32.exe -WorkingDirectory C:\EstGrp\CM\830\CM\USER

If you have been in a similar situation in needing to set the Working Directory, or some other attribute and have a more elegant solution please feel free to share it, either in the comments below or on Twitter.

WVD Spring Release > What’s New?

This post will focus on the changes made to the Windows Virtual Desktop (WVD) service by way of the Spring Release that went into Public Preview on Thursday 30th April 2020.

For ease, I’ll refer to the pre Spring Release WVD as version 1, and post Spring Release WVD as version 2.

Firstly, I’ve been a massive fan of WVD from the early days and was lucky enough to attend the Microsoft Airlift event in Seattle back in late September 2019 in which Microsoft officially announced its general availability – since then I’ve spent a considerable amount of time working with WVD, deploying it not only for internal use but for a number of large organisations, all with global workforces, who were looking to take advantage of its capabilities.

Now, I’m not going to say WVD version 1 was perfect, far from it, however, mindful that it was a first-generation product and Microsoft made it clear that their initial efforts were to build the multi-session capabilities into Windows 10 and additional functionality and supporting services, such as a much-requested native Azure portal-based management interface would follow soon.

Like many others in a similar position, I am extremely grateful to Marcel Meurer for producing his fantastic WVD Admin tool, this has saved me several hundred hours over the past months – to be honest, even with the newly released management interface (which I’ll cover later) I’m going to be hard pushed to not use WVD Admin going forward, it’s truly that good.

I’ve kept an eager-eye on the WVD Roadmap for months now,  hoping that the product team would make the new management UI available sooner rather than later, apologies to the guys at Microsoft who I’ve pestered no-end, especially Jim and Tom 🙂

So on Thursday 30th April Microsoft made the announcement that the Spring Release of WVD had moved out of private, and into public preview!

All I was expecting was the aforementioned new management interface, what we received, however, was essentially an entirely new WVD architecture!

My initial thoughts around the rearchitecting were, why? Why did WVD, a product that was less than 12 months old need such an overhaul? Now having spent a few days digging into version 2 it’s evidently clear, and in hindsight, it’s likely that I’d used WVD version 1 so much I’d become very robotic in the way I managed some of the less than elegant nuances, saying that, I’ve written close to 20 individual PowerShell scripts in that time to address these nuances so that should have given me some food for thought…

Anyway, what’s changed and why is such good news for those deploying, managing and using WVD going forward?

Firstly, WVD is now a first-party Azure service, to those who have deployed version 1 that means no more having to go through the steps of registering the app service in Azure granting consent (twice!) and having to run lines of PowerShell to create a tenant, in-fact Microsoft has done away with the concept of a tenant altogether!

Christian Brinkhoff provided a great diagram, below, showing how the WVD model has evolved in version 2, note the lack of tenant group and tenant.


In version 2 Microsoft has removed the hard-dependency between the host pool and apps or desktop groups, each component of the WVD architecture, that is, the workspace, host pool, app group, in line with Azure Resource Manager (ARM) is now modular and can be linked together to present resources to end-users (and groups, the Spring Release also brought this long-awaited functionality!)

Christian’s latest blog post on the Spring Update is essential reading so please check it out, Freek Berson‘s post on LinkedIn is brilliant too, not to forget Dean Cefola‘s Azure Academy YouTube channel – these guys provide an immense amount of content, information and inspiration for the wider WVD, EUC and Azure tech communities.

In place of the deprecated Tenant is now the Workspace, a Workspace is a collection of application and desktop resources presented to the end-user, in the screenshot below Core Apps, Finance Team and Tech Team are all Workspaces that the test user is assigned to.


Where this differs from version 1 is that in version 2 a single host pool can be associated to an application group and a desktop group at the same time, whereas in version 1 if you wanted to present applications and a desktop to the same user you would have had to deploy two separate host pools and associated virtual machines.

The relationship between components in the version 2 architecture is shown below.


As mentioned previously the Spring Release also brought the ability to use Azure AD groups (sync’d from AD) to assign users to WVD resources.

Users or groups are assigned access to the application or desktop group, those are associated with a hostpool (and underpinning sessions hosts, not shown in the diagram) and it is the hostpool that is assigned to the Workspace.

Even better than that, a single Workspace can be made up of multiple host pools!

Say you create a Workspace for the Graphic Design team at Company X and amongst the standard productivity tools the team use a resource-intensive application, you spin up an F series VM or similar and install the application on it, you want that application presented to the team in the same Workspace as their other apps but you don’t want to pay for all F series VM’s – with WVD version 2 you can spin up a host pool of cheaper general purpose session hosts for hosting MS Office etc and present the collective application stack to the team from a single Workspace, as below.


Note, multiple app groups can also be assigned to a single host pool.

So that concludes this article on the Spring Release of WVD however I’ll share more as I dig further into version 2.

Lastly, for those wondering as I did how to officially migrate your version 1 WVD workloads to WVD version 2, the answer is to sit tight for now, Microsoft will be releasing tooling soon to uplift the non-ARM deployments into ARM and version 2, as per Christiaan’s tweet below.


…that said, using version of WVD Admin it is quick and easy to use existing VM images to deploy into version 2 host pools, just follow this post.