Graphic depicting Microsoft PowerShell

In my recent “Getting to grips with WVD” post, I made reference to the emphasis on PowerShell for administration. I had a few questions in response and was keen to follow that post up with this; a WVD PowerShell reference. Hopefully it helps those of you out there who are looking to deploy Windows Virtual Desktop (WVD).

I don’t intend to include a lot of commentary around this post. It’s not an overview of WVD, or a deployment guide, but should help those of you who have taken the plunge with WVD at this early stage. By way of background, Microsoft have committed to a management console in time for its GA release. In the meantime, the only interface available is PowerShell – useful to learn, but not overly friendly for WVD specifically. The good news is that those familiar with RDS administration via PowerShell will feel right at home… 🙂

Connecting to the Service

Use the following command to connect to the WVD service, entering credentials when prompted (work or school account):

Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com"

A one time activity will be the creation of your WVD Tenant which is achieved by running::

New-RdsTenant -Name <TenantName> -AadTenantId <DirectoryID> -AzureSubscriptionId <SubscriptionID>

Working with a Service Principal

A Virtual Desktop Tenant “RDS Owner” account is needed for each Host Pool – this account is used to authenticate the pool to the WVD service. It’s likely you have MFA enabled for privileged accounts, in which case a Service Principal will be required.

The following commands are used to create the Service Principal:

Install-Module AzureAD
Import-Module AzureAD

$TenantGroupName = "Default Tenant Group"
$TenantName = "<Tenant Name>"

$aadContext = Connect-AzureAD
$svcPrincipal = New-AzureADApplication -AvailableToOtherTenants $true -DisplayName "Windows Virtual Desktop Service Principal"
$svcPrincipalCreds = New-AzureADApplicationPasswordCredential -ObjectId $svcPrincipal.ObjectId

Install-Module -Name Microsoft.RDInfra.RDPowerShell
Import-Module -Name Microsoft.RDInfra.RDPowerShell

Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com"
Set-RdsContext -TenantGroupName $TenantGroupName
New-RdsRoleAssignment -RoleDefinitionName "RDS Owner" -ApplicationId $svcPrincipal.AppId -TenantGroupName $TenantGroupName -TenantName $TenantName

Extract (and store securely) the Service Principal credentials for use in your Host Pool deployment by executing the command:

($svcPrincipalCreds.Value)

To validate the Service Principal can connect and access your WVD instance, use:

$svcPrincipalCredentials = New-Object System.Management.Automation.PSCredential($svcPrincipal.AppId, (ConvertTo-SecureString $svcPrincipalCreds.Value -AsPlainText -Force))
Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com" -Credential $svcPrincipalCredentials -ServicePrincipal -AadTenantId $aadContext.TenantId.Guid

Get-RdsHostPool -TenantName <Tenant Name>

Creating & Managing Host Pools

Host Pools house the Virtual Machines that deliver resources, along with Desktop and RemoteApp Application Groups. Whilst provisioning is far better addressed through the Azure Marketplace (“Windows Virtual Desktop – Provision a host pool”), there are some useful cmdlets available for Host Pool management.

Create a new pooled WVD Host Pool:

New-RdsHostPool -TenantName <Tenant Name> -Name <Host Pool Name>

Create a new persistent WVD Host Pool:

New-RdsHostPool -TenantName <Tenant Name> -Name <Host Pool Name> -Persistent

Retrieve details for a specific Host Pool:

Get-RdsHostPool -TenantName <Tenant Name>

Modify the properties of a Host Pool to specify breadth-first load balancing:

Set-RdsHostPool -TenantName <Tenant Name> -Name <Host Pool Name> -BreadthFirstLoadBalancer

Modify the properties of a Host Pool to specify depth-first load balancing:

Set-RdsHostPool -TenantName <Tenant Name> -Name <Host Pool Name> -DepthFirstLoadBalancer

Creating & Managing App Groups

Application Groups determine the type, and detail of resources published to assigned users. They have a Resource Type designation of either Desktop, or RemoteApp, but not both. A default “Desktop” App Group will be created as part of Host Pool creation via Azure.

Create a new Desktop App Group:

New-RdsAppGroup -TenantName <Tenant Name> -HostPoolName <Host Pool Name> -Name <App Group Name> -ResourceType Desktop

Create a new RemoteApp App Group:

New-RdsAppGroup -TenantName <Tenant Name> -HostPoolName <Host Pool Name> -Name <App Group Name> -ResourceType RemoteApp

Retrieve the properties of an App Group:

Get-RdsAppGroup -TenantName <Tenant Name> -HostPoolName <Host Pool Name> -Name <App Group Name>

Publishing & Managing RemoteApp Applications

In the case of a RemoteApp designation, Application Groups need to be populated with RemoteApp applications.

Retrieve available apps from your RemoteApp App host virtual machine(s). WVD will interrogate your image and list the available Start Menu items:

Get-RdsStartMenuApp <Tenant Name> <Host Pool Name> <Application Group Name> | Select FriendlyName,AppAlias

An example of the output from the default Windows 10 multi-user gallery image is as follows:

FriendlyName                   AppAlias
------------                   --------
Access                         access
Character Map                  charactermap
Database Compare               databasecompare
dfrgui                         dfrgui
Disk Cleanup                   diskcleanup
Excel                          excel
Internet Explorer              internetexplorer
iSCSI Initiator                iscsiinitiator
Math Input Panel               mathinputpanel
Memory Diagnostics Tool        memorydiagnosticstool
ODBC Data Sources (32-bit)     odbcdatasources32bit
ODBC Data Sources (64-bit)     odbcdatasources64bit
Office Language Preferences    officelanguagepreferences
Office Upload Center           officeuploadcenter
OneDrive                       onedrive
OneNote 2016                   onenote2016
Outlook                        outlook
Paint                          paint
PowerPoint                     powerpoint
Project Server Accounts        projectserveraccounts
Project                        project
Publisher                      publisher
Quick Assist                   quickassist
RecoveryDrive                  recoverydrive
Registry Editor                registryeditor
Remote Desktop Connection      remotedesktopconnection
Resource Monitor               resourcemonitor
Snipping Tool                  snippingtool
Spreadsheet Compare            spreadsheetcompare
Steps Recorder                 stepsrecorder
System Configuration           systemconfiguration
System Information             systeminformation
Task Manager                   taskmanager
Telemetry Dashboard for Office telemetrydashboardforoffice
Telemetry Log for Office       telemetrylogforoffice
Visio                          visio
Windows Fax and Scan           windowsfaxandscan
Windows Media Player           windowsmediaplayer
Windows Speech Recognition     windowsspeechrecognition
Word                           word
Wordpad                        wordpad

To create a RemoteApp based on an installed application:

New-RdsRemoteApp <Tenant Name> <Host Pool Name> <Application Group Name> -Name <Friendly Name> -AppAlias <App Alias>

By way of example, the following commands apply to the creation of the standard Office applications (Word, Excel, PowerPoint, and Outlook):

New-RdsRemoteApp <Tenant Name> <Host Pool Name> <Application Group Name> -Name "Word" -AppAlias word
New-RdsRemoteApp <Tenant Name> <Host Pool Name> <Application Group Name> -Name "Excel" -AppAlias excel
New-RdsRemoteApp <Tenant Name> <Host Pool Name> <Application Group Name> -Name "PowerPoint" -AppAlias powerpoint
New-RdsRemoteApp <Tenant Name> <Host Pool Name> <Application Group Name> -Name "Outlook" -AppAlias outlook

It’s possible to customise the command line parameters associated with a given application. For example, the passing of a command line argument to a web browser to launch a specific web page. This is achieved by specifying the “RequiredCommandLine” parameter of a published RemoteApp:

Set-RdsRemoteApp -TenantName <Tenant Name>  -HostPoolName <Host Pool Name> -AppGroupName <Application Group Name> -Name <Friendly Name> -CommandLineSetting Require -RequiredCommandLine <Additional Arguments> 

To list RemoteApp applications associated with a specific Application Group:

Get-RdsRemoteApp <Tenant Name> <Host Pool Name> <Application Group Name>

There will also be occasions where you want to remove RemoteApp’s from an Application Group. To do this, run:

Remove-RdsRemoteApp <Tenant Name> <Host Pool Name> <Application Group Name> -Name <Friendly Name>

Managing User Permissions to WVD Resources

Users need to be assigned to Application Groups within WVD. At present these need to be assigned explicitly using the following commands. The ability to assign permissions to groups is anticipated in time.

Permissions are applied to the Application Group, as opposed to specific resources (e.g. individual RemoteApp’s). To present different combinations of Applications to different users, multiple Application Groups are necessary.

Adding a user to an Application Group:

Add-RdsAppGroupUser <Tenant Name> <Host Pool Name> <Application Group Name> -UserPrincipalName <user@domain.com>

Removing a user from an Application Group:

Remove-RdsAppGroupUser <Tenant Name> <Host Pool Name> <Application Group Name> -UserPrincipalName <user@domain.com>

Managing User Sessions

As with more traditional RDS deployments, there will be occasions where the management of User Sessions is a requirement. We have a number of options available to us within WVD – many of which hinge off of the following command to list User Sessions running within a host pool:

Get-RdsUserSession <Tenant Name> <Host Pool Name>

Using the resulting Session Host, and Session ID information, we can invoke the following actions.

Disconnect a session:

Disconnect-RdsUserSession <Tenant Name> <Host Pool Name> -SessionHostName <Session Host Name> -SessionId <Session ID>

Log Off a user session:

Invoke-RdsUserSessionLogoff <Tenant Name> <Host Pool Name> -SessionHostName <Session Host Name> -SessionId <Session ID>

Send a notification to the user session:

Send-RdsUserSessionMessage <Tenant Name> <Host Pool Name> -SessionHostName <Session Host Name> -SessionId <Session ID> -MessageTitle <Title> -MessageBody <Message>

I hope you’ve found this WVD PowerShell reference useful. I’ll do my best to maintain it as Windows Virtual Desktop matures, and no doubt much of this functionality will make its way into the forthcoming Management Console.

If you haven’t already, I’d urge you to read my previous post which included some of the information in this post, along with a broader commentary on the features and functionality within WVD as a whole.