Enabling Remote Desktop on Multiple VMs

In my last post I shared with you how I setup VMs for MOC classes by using PowerShell. I also mentioned that I really enjoy using Remote Desktop to connect to my VMs in the classroom, and that I would share how I setup Remote Desktop by using PowerShell as well. And that is exactly what this blog post is all about, enabling Remote Desktop on all VMs for a given MOC course.

Enabling Remote Desktop is quite easy, and you will find multiple posts by using your favorite search engine on how that can be achieve by using WMI or registry settings. I prefer to use the registry. All you have to do is set the fDenyTSConnection value in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server key to 0 (zero). To do that in PowerShell, you need to run the following command:

Set-ItemProperty-Path'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'-NamefDenyTSConnection-Value0

However, we need to run this command on each virtual machine for a given course, and e will do that remotely. You can execute commands on a remote machine by using the Invoke-Command cmdlet. However, you need to ensure that the WinRM service is running on the remote machine, and that you have the right credentials to run PowerShell scripts remotely. The code below shows you how to create a credential object for remote authentication, and run the previous command we saw remotely:

$computerName    = 'LON-DC1'
$username        = 'ADATUM\Administrator'
$password        = 'Pa$$w0rd'

$password = ConvertTo-SecureString -String $password -Force -AsPlainText
$cred     = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password

Invoke-Command -ComputerName $computerName -Authentication Kerberos -Credential $Credential {Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnection -Value 0}

Finally, we need to run the remote command for all virtual machines in a course. And this is where things get tricky. Several courses have one or more Active Directory domains, and most computers are part of the domain. Therefore, we need to ensure that the domain controller is up and running to allow authentication to happen correctly. And to make matters worse, some courses have multiple versions of the same set of virtual machines. For instance, course 10747A has two versions for most virtual machines, a version entitled A, and another entitled B. You can see that by listing the VMs for the course and verifying that names of the VMs. If you find VMs with the exact same name, except for the ending, and the ending being -A, -B, -1 or -2, you are looking at a course with multiple VM versions. In scenarios like this, we need to ensure that the correct domain controller is available for authentication for each version.

The code below works with most MOC environments currently available. You might need to adjust the authentication settings for courses with multiple domains, or for workgroup computers.

function global:Enable-RDP {
     Param(
         $VMs,
         $Credential
     )
     # Start domain controllers
     $dcs = $VMs | ?{$_.Name.Contains("DC")}
     if ($dcs -ne $null)
     {
         foreach ($dc in $dcs)
         {
             Start-VM $dc
         }
         Start-Sleep -Seconds 240
     }
     # Cycle through all VMs
     foreach ($vm in $VMs)
     {
         # Start the VM if not a DC
         if (!$vm.Name.Contains("DC"))
         {
             Start-VM $vm
             Start-Sleep -Seconds 240
         }
         # Get computer name
         $computerName = $vm.Name.Substring($vm.Name.IndexOf('-')+1)
         if ($computerName[$computerName.Length - 2] -eq '-')
         {
             $computerName = $computerName.Substring(0, $computerName.Length -2)
         }
         # Enable Remote Desktop
         Invoke-Command -ComputerName $computerName -Authentication Kerberos -Credential $Credential {Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnection -Value 0}
         # Stop VM if not a DC
         if (!$vm.Name.Contains("DC"))
         {
             Stop-VM $vm -Confirm:$false
         }
     }
     # Stop all DCs
     if ($dcs -ne $null)
     {
         foreach ($dc in $dcs)
         {
             Stop-VM $dc -Confirm:$false
         }
     }
 }

 # Set course number
 $course          = '20417C'
 $username        = 'ADATUM\Administrator'
 $password        = 'Pa$$w0rd'
 $extraVMVersions = @('A',"B')

 # create credential
 $password = ConvertTo-SecureString -String $password -Force -AsPlainText
 $cred     = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password

 # Get all VMs for course, and DCs for course
 $course += "*"
 $vms    = Get-VM -Name $course

 # get multi-version envronments (-B, -C, etc)
 if ($extraVMVersions -ne $null)
 {
     foreach ($version in $extraVMVersions)
     {
         $versionVMs = $vms | ?{$_.Name.EndsWith($version)}
         Enable-RDP -VMs $versionVMs -Credential $cred
     }
 } else
 {
     Enable-RDP -VMs $vms -Credential $cred
 }

About telmosampaio

Father, husband, eternal student, trainer, developer, consultant and world traveler
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s