Local VM Management on Hyper-V Server with FreeRDP

A couple of weeks ago I blogged about the Veeam RDP virtual appliance for Remote Management of Hyper-V Server.  Since then I have been inundated with questions, opinions and information about different solutions for managing a Hyper-V server.  I have been spending some time looking at the various options – and one of my favorites has been FreeRDP.

To give some more context – if you are using the free version of Hyper-V Server (you can download it from here: https://technet.microsoft.com/en-us/evalcenter/dn205299.aspx) you can use the Hyper-V management tools remotely from a full installation of Windows.  But if you login locally to the server all you have is PowerShell.

Now, you can do almost everything through PowerShell.  Almost.  The one thing you cannot do is interact with a virtual machine directly.  Luckily – FreeRDP is a simple project that, amongst other things, supports connecting to Hyper-V virtual machines.

To test this out – I created a new Hyper-V Server – and attempted to create and configure the server without using any remote management tools.  After doing the initial server configuration – I used PowerShell to create a virtual switch:

get-netadapter | new-vmswitch -name "Virtual Switch" -AllowManagementOS $true

(Note, my server only had a single network adapter – so I cheated and made this command simple).

Then I created and started a virtual machine:

New-VM -Name "Test 1" -MemoryStartupBytes 1GB -Generation 1 -BootDevice LegacyNetworkAdapter -Path "C:\VMs\Test 1" -SwitchName "Virtual Switch" -NewVHDPath "C:\VMs\Test 1\VHD.vhdx" -NewVHDSizeBytes 40GB

Start-VM "Test 1"

Now we come to the part where I usually need to use a remote management solution.  I downloaded a Windows version of FreeRDP from here: https://www.cloudbase.it/freerdp-for-windows-nightly-builds/ and copied it to C:\FreeRDP on my Hyper-V Server.  To use FreeRDP to connect to a virtual machine – you need to know the virtual machine ID number.  To get this I ran:

Get-VM "Test 1" | Select ID

Which gave me a virtual machine ID of a0a23c9b-11ec-4740-82c5-2e0cf55674f4 (you will get a different one for your virtual machines). Then I  ran:

C:\FreeRDP\wfreerdp.exe /v:localhost:2179 /vmconnect:a0a23c9b-11ec-4740-82c5-2e0cf55674f4

Which worked!

However, I wanted a more elegant solution than this.  So I decided to write a script Cmdlet that would allow me to just provide the virtual machine name that I wanted to connect to:

 function Start-VMConnect 
    {
  
    [CmdletBinding()]
    param
       (
       # CMDLet takes a single parameter of VMNames. 
       # Can be single or plural, can come from the pipeline.
  
       [Parameter(Mandatory=$True,ValueFromPipeline=$True)]$VMnames
       )
  
    begin 
       {
       # Path to the binary for FreeRDP
  
       $FreeRDPPath = "C:\FreeRDP\wfreerdp.exe"
       }
  
    process 
       {
       foreach ($VMname in $VMnames) 
          {
          if ($pscmdlet.ShouldProcess($VMname)) 
             {
             # Get the ID of the virtual machine
             # If a VM object has been provided - grab the ID directly
             # Otherwise, try and get the VM object and get the ID from there
  
             if ($VMname.GetType().name -eq "VirtualMachine")
                {$VMID = $VMname.ID}
             else
                {$VMID = (get-vm $VMname | Select -first 1).ID}
  
             # Start FreeRDP
             start-process $FreeRDPPath -ArgumentList "/v:localhost:2179 /vmconnect:$($VMID)"
             }
          }
       }
  
    end {}
    }

This Cmdlet (Start-VMConnect) takes either a virtual machine name or a virtual machine object and then connects to it with FreeRDP.  As this is actually a script Cmdlet – you need to use Import-Module to load it:

image

Once it is loaded you can just use Start-VMConnect and connect to the virtual machine:

image

Very cool!  I liked this option most of everything I tried – as it was the smallest / lightest weight solution that solved all the problems that I had.

Thanks to Alessandro Pilotti, from Cloudbase Solutions, who gave me the pointers to this solution.

Cheers,
Ben

P.S. Here is a copy of my script Cmdlet:

vmconnect.zip