ra2 studio - Fotolia

How PowerShell Direct helps polish off those VMs

PowerShell Direct offers administrators a remoting option that does not rely on a network connection to manage Hyper-V VMs, but be sure you meet the requirements for its use.

PowerShell Direct is a very worthwhile tool for Hyper-V shops, especially if you haven't finished configuring your VMs, but there are some caveats to its use.

Microsoft released PowerShell 2.0 in late 2009, which introduced an eagerly awaited feature: the ability to connect and manage remote machines over Web Services for Management (WSMan). PowerShell Core 6.0 debuted Secure Shell (SSH) connections for PowerShell remoting in January 2018, but it's a slightly older remoting option, PowerShell Direct, that deserves a closer look.

Microsoft released PowerShell Direct with Windows Server 2016 and made it available on Windows 10. While WSMan and SSH require network connectivity to the remote machine, PowerShell Direct uses the VMBus to let you to remote into the virtual machine (VM) without network connectivity.

How to get started with PowerShell Direct

PowerShell Direct requires Windows PowerShell 5.1 or later. There are a number of other conditions to use PowerShell Direct to administer VMs on a Hyper-V host:

  • The Hyper-V host must run Windows Server 2016 or later, or Windows 10 (Creators Edition or later).
  • You must be logged on to the Hyper-V host as a Hyper-V administrator.
  • The VM must be either Windows 10 (Creators Edition or later) or Windows Server 2016 or later.
  • PowerShell must be 5.1 or later.
  • PowerShell needs to run with elevated privileges.
  • The VM to manage must be on the local Hyper-V host and running.
  • You need credentials on the VM.

PowerShell Direct isn't available to connect to Linux VMs, but you can use hvc.exe to connect to a Linux VM using SSH over the VMBus.


Using PowerShell Direct for Hyper-V management.

If you have a cluster of Hyper-V hosts, you can only connect to VMs with PowerShell Direct on the host you're logged on to. If a VM is running on another host, then you need to use WSMan-based PowerShell remoting in Windows PowerShell 5.1 and PowerShell Core 6.0 and up, SSH-based remoting in PowerShell Core 6.0 and up, or move the VM to the host you are on.

How to work with PowerShell Direct

With a standard WSMan-based PowerShell remoting session you supply the computer name to which you want to connect. In PowerShell Direct, you use the name of the VM or the VMId:

Get-VM W16AS01 | Format-List VMname, VMId

VMName : W16AS01

VMId : 2a1eabc2-e3cd-495c-a91f-51a1ad43104c

The VMId is a GUID; it takes a lot more effort to type correctly then the VM name. If the name of your VM isn't the same as the name of the machine inside the VM, be sure to use the VM name not the machine name.

The following commands create a remoting session to a VM:

$cred = Get-Credential -Credential manticore\richard

$s = New-PSSession -VMName W16AS01 -Credential $cred

$s1 = New-PSSession -VMId '2a1eabc2-e3cd-495c-a91f-51a1ad43104c' -Credential $cred

$s2 = New-PSSession -VMGuid '2a1eabc2-e3cd-495c-a91f-51a1ad43104c' -Credential $cred

If you don't supply a credential, you'll be prompted for one. VMGuid is a parameter alias for VMId.

After establishing a session, you can perform administration tasks as shown in the figure:

PowerShell Direct session
Figure 1. PowerShell Direct establishes a connection on a Hyper-V VM on a remote machine to run management jobs.

Invoke-Command -Session $s -ScriptBlock {Get-Process}

The following cmdlets have a -VMname and -VMid parameter: Enter-PSSession, Get-PSSession, Invoke-Command, New-PSSession, and Remove-PSSession

You can use Invoke-Command directly against the VM without creating a remoting session:

Invoke-Command -VMName W16AS01 -ScriptBlock {$env:COMPUTERNAME} -Credential $cred W16AS01

You must remember to supply the credentials for the machine each time you use Invoke-Command if you haven't created a remoting session.

One thing that trips up many new PowerShell users is the double-hop problem with PowerShell remoting. Take the following command:

Invoke-Command -ComputerName W16AS01 -ScriptBlock {Invoke-Command -ComputerName W16DC01 -ScriptBlock {$env:COMPUTERNAME}}

In this instance, the admin connects to a remote machine and then tries to run a command against a different remote machine, hence a double hop. The problem is Active Directory domains use Kerberos to manage authentication, and Kerberos does not allow credentials to be delegated to the first remote machine to use them to access the second machine. The attempt fails. You can overcome this by using Credential Security Support Provider to delegate your credentials, but a better approach is to plan ahead to avoid a double hop.

PowerShell Direct will allow the double hop because it doesn't use the WSMan-Kerberos approach, which avoids the delegation problem.

Invoke-Command -Session $s -ScriptBlock {Invoke-Command -ComputerName W16DC01 -ScriptBlock {$env:COMPUTERNAME}}

W16DC01

Invoke-Command -Session $s -ScriptBlock {Get-ADuser -Identity Richard}

PSComputerName  : W16AS01

RunspaceId    : 8351563d-57f6-4af6-aa77-ba00aa48490d

DistinguishedName : CN=Richard,CN=Users,DC=Manticore,DC=org

Enabled      : True

GivenName     : Richard

Name       : Richard

ObjectClass    : user

ObjectGUID    : 9b2b7185-15d2-4014-bc2c-41b04f5f6198

SamAccountName  : Richard

SID        : S-1-5-21-759617655-3516038109-1479587680-1104

Surname      :

UserPrincipalName : [email protected]

You can also connect to a VM using a PowerShell Direct connection and work remotely. For this tutorial, I'm using PowerShell Core 6.0.1.

Enter credentials
Figure 2. Enter your credentials to access the Hyper-V VM.

Start by getting the credentials you'll need for the remote machine. PowerShell Core doesn't include the Hyper-V module, so you'll import that into your PowerShell session. The Hyper-V module runs in PowerShell Core.

PowerShell Core 6.0 debuted Secure Shell (SSH) connections for PowerShell remoting in January 2018, but it's a slightly older remoting option, PowerShell Direct, that deserves a closer look.

The standard PowerShell Core 6.0 configuration doesn't include the Windows PowerShell 5.1 modules on the module path, so the auto-load is enabled. PowerShell Core 6.1, which does automatically include Windows PowerShell 5.1 modules on its module path, is now available. Users have six months from the September 2018 release of PowerShell Core 6.1 to upgrade from PowerShell Core 6.0 to stay in support.

Create and enter the session to the remote machine. If you already have an existing session, you can enter that. For example:

Enter-PSSession -Session $s

[W16AS01]: PS C:\Users\Richard\Documents>

In either case, the prompt changes to include the VM name. You can then work interactively as if you were logged on to the remote machine. Use Exit-PSSession to leave the PowerShell remote session.

Be mindful of your PowerShell Core versions

When you use PowerShell Direct, by default you connect to the Windows PowerShell 5.1 instance on the VM. This happens when you connect from a Windows PowerShell 5.1 or a PowerShell Core 6.0 instance on your Hyper-V host.

This behavior changes in PowerShell Core 6.1.  If you have Windows PowerShell 5.1 and PowerShell Core 6.1 on the host and only Windows PowerShell 5.1 on the VM, then you connect to the VM's Windows PowerShell 5.1 instance as before.

If you have Windows PowerShell 5.1 and PowerShell Core 6.1 on the host and on the VM, PowerShell Direct attempts to connect to PowerShell Core 6.1 (using the pwsh.exe executable) first and if it is unable to connect, drops back to Windows PowerShell 5.1 (using the PowerShell.exe executable). This means you have to think about the PowerShell functionality on the VM and if it will run under PowerShell Core 6.1.

Keep an eye on the PowerShell project to stay on top of the changes from the Microsoft team. It's always a good idea to test the $PSVersionTable on the VM to check the version of PowerShell.

Dig Deeper on Microsoft messaging and collaboration

Cloud Computing
Enterprise Desktop
Virtual Desktop
Close