Summary: How to use Azure AD DS and Window Virtual Desktop as a Test Environment.
Date: Around 2020
Refactor: 20 February 2025: Checked links and formatting.
Note: This article was originally created in the first few months in 2020, before the Corona pandemic reached Europe and the US. Forced by the pandemic Microsoft made a lot of steps in this manual a lot more easy, and this article probably less relevant.
In this article the following services are being used:
As we want to test in completely separated and empty environment the best way forward is to create an new empty environment. Usually you could create a free account but I used one before and free accounts are limited to 1 per customer. So I decided to create a new subscription:
This might take a while, but afterwards you'll be the proud owner of an additional subscription.
The first step we need to do now is to create a new tenant and associate that with this subscription.
Note that a subscription can only trust one directory, but a directory can trust multiple subscriptions
Now that we've created the directory we have to associate it with the new subscription:
Now, in the subscriptions overview, to see the new subscription, use “Switch Directories” to see the new subscription. The documentation mentioned it could take hours for everything to show correctly, so make sure everything looks ok before you continue.
For now we'll create a basic instance. This will create an instance with the default configuration settings for networking and synchronization.
Note that provisioning a domain can take up to more than an hour. To check the progress click on the resource group (RG_AzureADDS) and then on the Azure AD Domain Services object (aadtest001getsh.onmicrosoft.com) in the list of resources.
You can also download a template for automation. This will provide two files:
Template.json
- template.json
{ "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "apiVersion": { "type": "string" }, "sku": { "type": "string" }, "domainConfigurationType": { "type": "string" }, "domainName": { "type": "string" }, "filteredSync": { "type": "string" }, "location": { "type": "string" }, "notificationSettings": { "type": "object" }, "subnetName": { "type": "string" }, "vnetName": { "type": "string" }, "vnetAddressPrefixes": { "type": "array" }, "subnetAddressPrefix": { "type": "string" }, "nsgName": { "type": "string" } }, "resources": [ { "apiVersion": "2017-06-01", "type": "Microsoft.AAD/DomainServices", "name": "[parameters('domainName')]", "location": "[parameters('location')]", "dependsOn": [ "[concat('Microsoft.Network/virtualNetworks/', parameters('vnetName'))]" ], "properties": { "domainName": "[parameters('domainName')]", "subnetId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/virtualNetworks/', parameters('vnetName'), '/subnets/', parameters('subnetName'))]", "filteredSync": "[parameters('filteredSync')]", "domainConfigurationType": "[parameters('domainConfigurationType')]", "notificationSettings": "[parameters('notificationSettings')]", "sku": "[parameters('sku')]" } }, { "type": "Microsoft.Network/NetworkSecurityGroups", "name": "[parameters('nsgName')]", "location": "[parameters('location')]", "properties": { "securityRules": [ { "name": "AllowSyncWithAzureAD", "properties": { "access": "Allow", "priority": 101, "direction": "Inbound", "protocol": "Tcp", "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", "sourcePortRange": "*", "destinationAddressPrefix": "*", "destinationPortRange": "443" } }, { "name": "AllowPSRemoting", "properties": { "access": "Allow", "priority": 301, "direction": "Inbound", "protocol": "Tcp", "sourceAddressPrefix": "AzureActiveDirectoryDomainServices", "sourcePortRange": "*", "destinationAddressPrefix": "*", "destinationPortRange": "5986" } }, { "name": "AllowRD", "properties": { "access": "Allow", "priority": 201, "direction": "Inbound", "protocol": "Tcp", "sourceAddressPrefix": "CorpNetSaw", "sourcePortRange": "*", "destinationAddressPrefix": "*", "destinationPortRange": "3389" } } ] }, "apiVersion": "2019-09-01" }, { "type": "Microsoft.Network/virtualNetworks", "name": "[parameters('vnetName')]", "location": "[parameters('location')]", "apiVersion": "2019-09-01", "dependsOn": [ "[concat('Microsoft.Network/NetworkSecurityGroups/', parameters('nsgName'))]" ], "properties": { "addressSpace": { "addressPrefixes": "[parameters('vnetAddressPrefixes')]" }, "subnets": [ { "name": "[parameters('subnetName')]", "properties": { "addressPrefix": "[parameters('subnetAddressPrefix')]", "networkSecurityGroup": { "id": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/NetworkSecurityGroups/', parameters('nsgName'))]" } } } ] } } ], "outputs": {} }
Parameters.json * Changed the email address under additionalRecipients
- parameters.json
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "apiVersion": { "value": "2017-06-01" }, "sku": { "value": "Standard" }, "domainConfigurationType": { "value": "FullySynced" }, "domainName": { "value": "aadtest001getsh.onmicrosoft.com" }, "filteredSync": { "value": "Disabled" }, "location": { "value": "westeurope" }, "notificationSettings": { "value": { "notifyGlobalAdmins": "Enabled", "notifyDcAdmins": "Enabled", "additionalRecipients": [ "test@test.com" ] } }, "subnetName": { "value": "aadds-subnet" }, "vnetName": { "value": "aadds-vnet" }, "vnetAddressPrefixes": { "value": [ "10.0.0.0/24" ] }, "subnetAddressPrefix": { "value": "10.0.0.0/24" }, "nsgName": { "value": "aadds-nsg" } } }
DNS is a key resource for an Active Directory Domain, and you need to configure the virtual network with the new DNS settings.
In this setup, we only have one user so far. Usually you would have users change their passwords before they can use Azure AD Domain Services. We will now create users so we can use Azure AD Domain Services.
Repeat the steps above for:
Use Cloud Shell to setup a permanent password:
$pass = ConvertTo-SecureString -String "NewPass123!!" -AsPlainText -Force Connect-AzureAD Set-AzureADUserPassword -ObjectId "4d6ea095-ec2b-491f-b785-ee68f32661be" -ForceChangePasswordNextLogin $false -Password $pass #testuser: Set-AzureADUserPassword -ObjectId "c4e719d6-d895-49d8-9d58-099c971f8770" -ForceChangePasswordNextLogin $false -Password $pass #poweruser: Set-AzureADUserPassword -ObjectId "0533f49d-5ffb-476c-8f8a-433b175f5be7" -ForceChangePasswordNextLogin $false -Password $pass
Now that Azure AD Domain Services is correctly deployed it would actually be nice that we can manage it. During the deployment we configured the default settings, which created a separate virtual network and subnet for the Azure AD Domain Services. It is recommended to use this subnet only for the Azure AD Domain Services, which means we can create additional subnets or create additional networks and peer the networks. We will create a virtual subnet:
Now that we've created a management network we can create a management server and join the server to the domain.
This might take a few minutes, once the deployment is done you can click “Setup auto-shutdown” to configure automatic shutdown of the VM, in case you might ever forget:
To connect to the Management VM we'll use Azure Bastion, which you could see as a gateway or stepping stone server between the internet and your private network in Azure. Do note that this is https://azure.microsoft.com/en-us/pricing/details/azure-bastion/
Once the Bastion Host is created it is possible to connect to the VM using only your browser.
Once you've logged in to the VM, you can start to join it to the domain and install management tools
Now the Management VM will reboot, and afterwards you can login using Bastion and the sjoerdadmin credentials. We will now install the Remote Server Administration Tools.
Now you can use the Active Directory, DNS and Group Policy Management administration tools from the Server Manager → Tools section.
Note that before you can manage DNS you need to connect to a DNS server. You can fill in the domain name (aadtest001getsh.onmicrosoft.com) to automatically connect to one.
Now that we have a working Active Directory environment in the cloud we also want to provide applications to users. We will use Windows Virtual Desktop for that. This is, right now, quite a new service, and a lot of individual steps are required. We start with creating a tenant in Windows Virtual Desktop. We need a Global administrator for this, but we can't use the original global administrator because that one is part of a different directory. This shows in Azure Active Directory which shows the account as from an External Azure Active Directory.
Now open a browser as the specified user. To do so, login to the Management VM, and start by disabling “IE Enhanced Security Configuration” for administrators under the Local Server properties in Server Manager. Then start Internet Explorer.
Now that we've performed all required steps we can actually create a Windows Virtual Desktop client. Unfortunately that is done with a legacy powershell module, which means we can't use the previously configured cloud shell. Windows Server 2019 still comes with PowerShell 5.1 so we will do these steps from the Management VM. Start PowerShell as administrator as we will first install the required module.
Install-Module -Name Microsoft.RDInfra.RDPowerShell Import-Module -Name Microsoft.RDInfra.RDPowerShell Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com" # use the sjoerdadmin@aadtest001getshifting.onmicrosoft.com account to log in New-RdsTenant -Name virtualdesktoptest001 -AadTenantId 569b3e72-89ce-4115-9858-ce53d8e5c490 -AzureSubscriptionId c18b1986-f82f-4809-838a-39cfe062f21b # Optionally you could assign administrative access to a second user New-RdsRoleAssignment -TenantName <TenantName> -SignInName <Upn> -RoleDefinitionName "RDS Owner"
Note that once installed, you can perform the succeeding steps in a non-administrative powershell session
Service principals are identities that you can create in Azure Active Directory to assign roles and permissions for a specific purpose. In Windows Virtual Desktop, you can create a service principal to “Automate specific Windows Virtual Desktop management tasks” and “Use as credentials in place of MFA-required users when running any Azure Resource Manager template for Windows Virtual Desktop”.
We start by installing the AzureAD powershell module in an administrative powershell session
Install-Module AzureAD
Then run the following commands:
import-module Microsoft.RDInfra.RDPowershell import-module AzureAD $aadContext = Connect-AzureAD # use the sjoerdadmin@aadtest001getshifting.onmicrosoft.com account to log in $svcPrincipal = New-AzureADApplication -AvailableToOtherTenants $true -DisplayName "Windows Virtual Desktop Svc Principal" $svcPrincipalCreds = New-AzureADApplicationPasswordCredential -ObjectId $svcPrincipal.ObjectId # Now you need three essential pieces of information # The Password $svcPrincipalCreds.Value R0SeCl0PevMnhbyHBcvinlTuc9WHlsSNL7E2iqfHtSU= # Tenant ID $aadContext.TenantId.Guid 569b3e72-89ce-4115-9858-ce53d8e5c490 # Application ID $svcPrincipal.AppId 1bbce553-9951-41a8-b527-b6a0d2d30479 # Now we create the role assignments Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com" # use the sjoerdadmin@aadtest001getshifting.onmicrosoft.com account to log in Get-RdsTenant # This displayes the TenantName (among other information), please note it: virtualdesktoptest001 $myTenantName = "virtualdesktoptest001" New-RdsRoleAssignment -RoleDefinitionName "RDS Owner" -ApplicationId $svcPrincipal.AppId -TenantName $myTenantName $creds = New-Object System.Management.Automation.PSCredential($svcPrincipal.AppId, (ConvertTo-SecureString $svcPrincipalCreds.Value -AsPlainText -Force)) Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com" -Credential $creds -ServicePrincipal -AadTenantId $aadContext.TenantId.Guid
Before we can create the hostpool we first need to disable MFA for the account that will perform the domain join. For new tenants, the security defaults now include MFA, which is not supported for accounts that are used for the domain join of Windows Virtual Desktop hosts.
Create a hostpool to host the VMs that will be acting as the Windows Virtual Desktop.
Get-RdsTenant
powershell command.Note that if you want to add additional users to the desktop application group you need to do so using powershell:Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com" Add-RdsAppGroupUser <tenantname> <hostpoolname> "Desktop Application Group" -UserPrincipalName <userupn>
To remove users:
Get-RdsAppGroup Virtualdesktoptest001 HostPool_Desktop01 #Remove-RdsAppGroupUser -TenantName "contoso" -HostPoolName "contosoHostPool" -AppGroupName "officeApps" -UserPrincipalName "user1@contoso.com" Remove-RdsAppGroupUser -TenantName Virtualdesktoptest001 -HostPoolName HostPool_Desktop01 -AppGroupName "Desktop Application Group" -UserPrincipalName "sjoerdpower@aadtest001getshifting.onmicrosoft.com"
There are several options to connect to the virtual desktop, but, some work better than others. You have the https://docs.microsoft.com/en-us/azure/virtual-desktop/connect-windows-7-and-10 but it requires a few firewall urls to be opened, which is not always convenient when doing tests. I found the best solution was to use the https://docs.microsoft.com/en-us/azure/virtual-desktop/connect-web, which involved to startup a private chrome broweser window, connect to https://rdweb.wvd.microsoft.com/webclient and login using the sjoerdtest@aadtest001getshifting.onmicrosoft.com account.
After logging in you first see the Virtual Desktop Tenant: Virtualdesktoptest001, and when clicking through you'll be presented with the HostPool: HostPool_Desktop01 which will connect you with the actual desktop. Note that you also need to logon to the desktop itself, again using the sjoerdtest account.
Now that we have a working desktop I also want to be able to publish a single application. To do so, we will work again with the Windows Virtual Desktop PowerShell module which is installed on the management server
import-module Microsoft.RDInfra.RDPowershell # Login with your sjoerdadmin account: sjoerdadmin@aadtest001getshifting.onmicrosoft.com Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com" # Create a new empty RemoteApp app group # New-RdsAppGroup <tenantname> <hostpoolname> <appgroupname> -ResourceType "RemoteApp" New-RdsAppGroup Virtualdesktoptest001 HostPool_Desktop01 WindowsApps -ResourceType "RemoteApp" # Verify # Get-RdsAppGroup <tenantname> <hostpoolname> Get-RdsAppGroup Virtualdesktoptest001 HostPool_Desktop01 # Get a list of Start menu apps on the host pool's virtual machine image. Write down the values for FilePath, IconPath, IconIndex and the AppAlias. # Get-RdsStartMenuApp <tenantname> <hostpoolname> <appgroupname> Get-RdsStartMenuApp Virtualdesktoptest001 HostPool_Desktop01 WindowsApps <# TenantGroupName : Default Tenant Group TenantName : Virtualdesktoptest001 HostPoolName : HostPool_Desktop01 AppGroupName : WindowsApps AppAlias : snippingtool FriendlyName : Snipping Tool FilePath : C:\windows\system32\SnippingTool.exe CommandLineArguments : IconPath : C:\windows\system32\SnippingTool.exe IconIndex : 0 TenantGroupName : Default Tenant Group TenantName : Virtualdesktoptest001 HostPoolName : HostPool_Desktop01 AppGroupName : WindowsApps AppAlias : taskmanager FriendlyName : Task Manager FilePath : C:\windows\system32\taskmgr.exe CommandLineArguments : /7 IconPath : C:\windows\system32\Taskmgr.exe IconIndex : -30651 TenantGroupName : Default Tenant Group TenantName : Virtualdesktoptest001 HostPoolName : HostPool_Desktop01 AppGroupName : WindowsApps AppAlias : wordpad FriendlyName : Wordpad FilePath : C:\Program Files\Windows NT\Accessories\wordpad.exe CommandLineArguments : IconPath : C:\Program Files\Windows NT\Accessories\wordpad.exe IconIndex : 0 #> # Run the following cmdlet to install the application based on AppAlias # New-RdsRemoteApp <tenantname> <hostpoolname> <appgroupname> -Name <remoteappname> -AppAlias <appalias> New-RdsRemoteApp Virtualdesktoptest001 HostPool_Desktop01 WindowsApps -Name "Snipping Tool" -AppAlias snippingtool New-RdsRemoteApp Virtualdesktoptest001 HostPool_Desktop01 WindowsApps -Name "Task Manager" -AppAlias taskmanager New-RdsRemoteApp Virtualdesktoptest001 HostPool_Desktop01 WindowsApps -Name Wordpad -AppAlias wordpad # Verify # Get-RdsRemoteApp <tenantname> <hostpoolname> <appgroupname> Get-RdsRemoteApp Virtualdesktoptest001 HostPool_Desktop01 WindowsApps # Grant users access. Note that within a hostgroup you can't assign users to both desktop and remote app groups. #Add-RdsAppGroupUser <tenantname> <hostpoolname> <appgroupname> -UserPrincipalName <userupn> Add-RdsAppGroupUser Virtualdesktoptest001 HostPool_Desktop01 WindowsApps -UserPrincipalName "sjoerdpower@aadtest001getshifting.onmicrosoft.com"
Now you can user the poweruser to login through the https://rdweb.wvd.microsoft.com/webclient and access the published apps.
You can also add an application which is not listed as publishable in the Get-RdsStartMenuApp command. Notepad is not listed, but you can add it like this:
#New-RdsRemoteApp <tenantname> <hostpoolname> <appgroupname> -Name <remoteappname> -Filepath <filepath> -IconPath <iconpath> -IconIndex <iconindex> New-RdsRemoteApp Virtualdesktoptest001 HostPool_Desktop01 WindowsApps -Name Notepad -Filepath "C:\WINDOWS\system32\notepad.exe" -IconPath "C:\WINDOWS\system32\notepad.exe" -IconIndex 0
We will now create a Master Image with a business application. For this test we will use VSCode with a few extensions.
Once the VM is created you can login using Bastion and the credentials provided during VM creation.
Follow the steps as explained https://docs.microsoft.com/en-us/azure/virtual-desktop/set-up-customize-master-image and https://docs.microsoft.com/en-us/azure/virtual-desktop/install-office-on-wvd-master-image and https://docs.microsoft.com/en-us/azure/virtual-desktop/create-host-pools-user-profile#configure-the-fslogix-profile-container
Setup.exe /configure configuration.xml
<Configuration> <Add OfficeClientEdition="64" Channel="Monthly"> <Product ID="O365ProPlusRetail"> <Language ID="en-US" /> <Language ID="MatchOS" /> <ExcludeApp ID="Groove" /> <ExcludeApp ID="Lync" /> <ExcludeApp ID="OneDrive" /> <ExcludeApp ID="Teams" /> </Product> </Add> <RemoveMSI/> <Updates Enabled="FALSE"/> <Display Level="None" AcceptEULA="TRUE" /> <Logging Level=" Standard" Path="%temp%\WVDOfficeInstall" /> <Property Name="FORCEAPPSHUTDOWN" Value="TRUE"/> <Property Name="SharedComputerLicensing" Value="1"/> </Configuration>
rem Mount the default user registry hive reg load HKU\TempDefault C:\Users\Default\NTUSER.DAT rem Must be executed with default registry hive mounted. reg add HKU\TempDefault\SOFTWARE\Policies\Microsoft\office\16.0\common /v InsiderSlabBehavior /t REG_DWORD /d 2 /f rem Set Outlook's Cached Exchange Mode behavior rem Must be executed with default registry hive mounted. reg add "HKU\TempDefault\software\policies\microsoft\office\16.0\outlook\cached mode" /v enable /t REG_DWORD /d 1 /f reg add "HKU\TempDefault\software\policies\microsoft\office\16.0\outlook\cached mode" /v syncwindowsetting /t REG_DWORD /d 1 /f reg add "HKU\TempDefault\software\policies\microsoft\office\16.0\outlook\cached mode" /v CalendarSyncWindowSetting /t REG_DWORD /d 1 /f reg add "HKU\TempDefault\software\policies\microsoft\office\16.0\outlook\cached mode" /v CalendarSyncWindowSettingMonths /t REG_DWORD /d 1 /f rem Unmount the default user registry hive reg unload HKU\TempDefault rem Set the Office Update UI behavior. reg add HKLM\SOFTWARE\Policies\Microsoft\office\16.0\common\officeupdate /v hideupdatenotifications /t REG_DWORD /d 1 /f reg add HKLM\SOFTWARE\Policies\Microsoft\office\16.0\common\officeupdate /v hideenabledisableupdates /t REG_DWORD /d 1 /f
"C:\stage\OneDriveSetup.exe" /uninstall
or through the Apps and FeaturesREG ADD "HKLM\Software\Microsoft\OneDrive" /v "AllUsersInstall" /t REG_DWORD /d 1 /reg:64
"C:\stage\OneDriveSetup.exe" /allusers
REG ADD "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v OneDrive /t REG_SZ /d "C:\Program Files (x86)\Microsoft OneDrive\OneDrive.exe /background" /f
REG ADD "HKLM\SOFTWARE\Policies\Microsoft\OneDrive" /v "SilentAccountConfig" /t REG_DWORD /d 1 /f
REG ADD "HKLM\SOFTWARE\Policies\Microsoft\OneDrive" /v "KFMSilentOptIn" /t REG_SZ /d "<your-AzureAdTenantId>" /f
REG ADD "HKLM\SOFTWARE\Policies\Microsoft\OneDrive" /v "KFMSilentOptIn" /t REG_SZ /d "569b3e72-89ce-4115-9858-ce53d8e5c490" /f
STEP BELOW REQUIRES ANOTHER VM TO ACT AS A FILE SHARE SEE → https://docs.microsoft.com/en-us/azure/virtual-desktop/create-host-pools-user-profile#configure-the-fslogix-profile-container
* FSLogix profile container
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v NoAutoUpdate /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fEnableTimeZoneRedirection /t REG_DWORD /d 1 /f
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy" /v 01 /t REG_DWORD /d 0 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v MaxMonitors /t REG_DWORD /d 4 /f reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v MaxXResolution /t REG_DWORD /d 5120 /f reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v MaxYResolution /t REG_DWORD /d 2880 /f reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\rdp-sxs" /v MaxMonitors /t REG_DWORD /d 4 /f reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\rdp-sxs" /v MaxXResolution /t REG_DWORD /d 5120 /f reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\rdp-sxs" /v MaxYResolution /t REG_DWORD /d 2880 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v RemoteAppLogoffTimeLimit /t REG_DWORD /d 0 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fResetBroken /t REG_DWORD /d 1 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v MaxConnectionTime /t REG_DWORD /d 10800000 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v RemoteAppLogoffTimeLimit /t REG_DWORD /d 0 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v MaxDisconnectionTime /t REG_DWORD /d 5000 /f reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v MaxIdleTime /t REG_DWORD /d 10800000 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" /v SpecialRoamingOverrideAllowed /t REG_DWORD /d 1 /f
In this case we will just install Visual Studio Code with the powershell extension:
Now clean up (also empty the recycle bin) all downloaded files, and optionally reboot the vm if you like to.
In case you might want to go back to this point to install additional software you can create a https://docs.microsoft.com/en-us/azure/virtual-machines/windows/snapshot-copy-managed-disk
Not that you can view a list of snaphost in the Azure Potal by searching and selecting for snapshot. It also shows in the
c:\Windows\System32\Sysprep\sysprep.exe
Now we can create an image from the Golden Image VM. Note that this can not be undone and makes the VM unusable
We can now create a hostpool based on the VM. This is almost identical to the hostpool we create before. See below for the steps, and note that the differences are in bold.
Create a hostpool to host the VMs that will be acting as the Windows Virtual Desktop.
Get-RdsTenant
powershell command.Startup a private chrome broweser window, connect to https://rdweb.wvd.microsoft.com/webclient and login using the sjoerdtest@aadtest001getshifting.onmicrosoft.com account.
After logging in you first see the Virtual Desktop Tenant: Virtualdesktoptest001, which now holds the Published Remote Apps and the Desktop VSCode-Desktop.
The powershell extension is not available in Visual Studio Code, so this might a per user installation.
Unfortunately, you can't use the azure portal to restore a VM from the snapshot. And you also can't just reuse the VM. You can use powershell to create a new VM using the snapshot. You can use the powershell script below in Cloud Shell, as we have used before.
Connect-AzureAD #Provide the subscription Id $subscriptionId = 'c18b1986-f82f-4809-838a-39cfe062f21b' #Provide the name of your resource group $resourceGroupName ='RG_AzureADDS' #Provide the name of the snapshot that will be used to create OS disk $snapshotName = '20200312-PreSysPrep' #Provide the name of the OS disk that will be created using the snapshot $osDiskName = 'vm-we-w10-img02_OsDisk_1' #Provide the name of an existing virtual network where virtual machine will be created $virtualNetworkName = 'aadds-vnet' #Provide the name of the virtual machine $virtualMachineName = 'vm-we-w10-img02' #Provide the size of the virtual machine # get-azvmsize -location westeurope $virtualMachineSize = 'Standard_B2s' #Set the context to the subscription Id where Managed Disk will be created Select-AzSubscription -SubscriptionId $SubscriptionId $snapshot = Get-AzSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName $diskConfig = New-AzDiskConfig -Location $snapshot.Location -SourceResourceId $snapshot.Id -CreateOption Copy $disk = New-AzDisk -Disk $diskConfig -ResourceGroupName $resourceGroupName -DiskName $osDiskName #Initialize virtual machine configuration $VirtualMachine = New-AzVMConfig -VMName $virtualMachineName -VMSize $virtualMachineSize #Use the Managed Disk Resource Id to attach it to the virtual machine. $VirtualMachine = Set-AzVMOSDisk -VM $VirtualMachine -ManagedDiskId $disk.Id -CreateOption Attach -Windows #Get the virtual network where virtual machine will be hosted $vnet = Get-AzVirtualNetwork -Name $virtualNetworkName -ResourceGroupName $resourceGroupName # Create NIC in the first subnet of the virtual network $nic = New-AzNetworkInterface -Name ($VirtualMachineName.ToLower()+'_nic') -ResourceGroupName $resourceGroupName -Location $snapshot.Location -SubnetId $vnet.Subnets[0].Id # Add the nic to the virtual machine $VirtualMachine = Add-AzVMNetworkInterface -VM $VirtualMachine -Id $nic.Id #Create the virtual machine with Managed Disk New-AzVM -VM $VirtualMachine -ResourceGroupName $resourceGroupName -Location $snapshot.Location
Note that this connects the VM to the first subnet: $vnet.Subnets[0].Id . You could check with$vnet
what the id is of the VDI subnet and use that, or change the subnet afterwards.
Then when the machine is done creating, you can test the VM by starting it and logging in (through Bastion). Note that the original local credentials are in use that were originally were used to install the VM vm-we-w10-img01. This means that the powershell extension in VSCode is also back!
The total costs of creating this over the course of about 10 days was 37,84 euro:
Follow these guidelines to minimize the costs, especially for test environments.