Testing PowerShell Direct with Windows Server 2016 TP3 Hyper-V

PowerShell for Admins, Training

Hey there! I  thought we could test PowerShell Direct together today. Here's the elevator pitch: In Windows Server 2016 and Windows 10, we can send PowerShell commands from the Hyper-V host directly to its corresponding virtual machines (VMs), even in the absence of guest VM networking. Yeah, that's cool, isn't it?

What's just as impressive is that PowerShell Direct works even if PowerShell remoting is disabled on the guest VM! PowerShell Direct also circumvents Windows Firewall. Note that PowerShell Direct requires that commands are sent only from a Hyper-V host to its local VMs.

Also, PowerShell Direct is supported at this point only by Windows Server 2016 TP3 and Windows 10. That means a Windows Server 2016 TP3 Hyper-V host cannot leverage PowerShell Direct against, say, Windows Server 2012 R2 virtual machines (give the Hyper-V, PowerShell, and Windows Server teams time; I'm sure this will be supported in the future).

The secret sauce behind PowerShell Direct is PowerShell Remoting Protocol (MS-PSRP), which used to be called just plain ol' garden variety "PowerShell remoting."

The Lab Setup

In my test lab, I started with a domain controller and Hyper-V host (yeah, I'm combining server roles--what of it?) named hyperv1.company.pri. That server's running Windows Server 2016 Technical Preview 3.

In Hyper-V I created a single virtual switch named Internal that is connected to the host/guest network. Of course, we don't care about the switch fabric because we're going to use PowerShell Direct.

Next, I built a Windows Server 2016 TP3-based guest VM named server1 and disabled the network adapter as you can see in the following screenshot. No smoke and mirrors here!

Our lab is set up and ready to test PowerShell Direct.

Our lab is set up and ready to test PowerShell Direct.

As a final "sanity check" to ensure the guest VM is as theoretically inaccessible as possible, I blocked access to all remote access session configurations and disabled the Windows Remote Management (WinRM) service by running the following command from within the guest (thanks to PowerShell MVP Aleksandar Nikolić for clarification on this point):

Disable-PSRemoting -Force
Get-Service -Name WinRM | Stop-Service -Force | Set-Service -StartupType Disabled

Okay. Let's move onto the next phase of our experiment.

Sending Commands to the Guest VM

Let's obtain the name and globally unique identifier (GUID) of our Windows Server 2016 VM (you'll see why in just a moment):

Get-VM | Select-Object -Property Name, VMid
Name        VMId
----        ----
server1     31d787fe-02cd-4363-b50b-16bc8243fc77

PowerShell Direct makes itself manifest by means of two new parameters:

  • VMname
  • VMGuid

Handy, eh? The following two cmdlets support the -VMname and -VMGuid parameters as of this writing in October 2016:

Time to test! Let's start a remote session with the server1 guest VM by specifying its GUID. Note that you will need:

  • Hyper-V administrative privileges on the host
  • Local administrative privileges on the guest
$cred = Get-Credential
Enter-PSSession -VMGuid 31d787fe-02cd-4363-b50b-16bc8243fc77 -Credential $cred
[server1]: PS C:\Users\Administrator\Documents>

We'll finish by using Invoke-Command to send ad-hoc PowerShell pipelines and entire scripts from host to guest:

Invoke-Command -VMName 'server1' -Credential $cred -ScriptBlock { Get-Service | Where-Object {$_.Status -eq 'Stopped'} }
Invoke-Command -VMName 'server1' -FilePath 'D:\scripts\setup-ip.ps1' -Credential $cred


Convenience is the primary advantage that PowerShell Direct brings to us Hyper-V administrators. We can connect to and fully administer our guest virtual machines regardless of their networking, firewall, or WS-Man state. Thanks for reading, and more power to the shell!

Comments are closed.