Posey's Tips & Tricks

Managing Hyper-V VMs with PowerShell Direct

Here's how to use PowerShell to manage Hyper-V virtual machines without having to jump through the usual hoops.

Microsoft has long given administrators the ability to use PowerShell to manage remote machines through the use of commands such as Enter-PSSession. Even so, it can sometimes be a little bit cumbersome to set up PowerShell remoting.

Thankfully, a feature called PowerShell Direct allows Hyper-V admins to use PowerShell to manage Hyper-V virtual machines (VMs) without having to jump through the usual hoops.

The Usual Way of Doing Things
Normally, if you want to be able to remotely manage a Windows machine (physical or virtual) using PowerShell, you have to enable PowerShell Remoting (which Microsoft refers to as PSRemoting). If the system is domain-joined, this is an easy process. You simply log on to the machine and enter the following command into an administrative PowerShell window:

Enable-PSRemoting -Force

This command does a few different things to prepare the system for remote PowerShell management. The Force part of the command isn't actually required -- it just keeps PowerShell from nagging you for permission at every step of the process. So what specifically does the Enable-PSRemoting cmdlet do? Well, it starts the WinRM service, and also configures the service to start automatically any time that the system is booted. It also sets up a firewall exception to allow remote management of the computer.

Preparing the computer for remote management is a far more complicated process if the computer is not domain-joined, but that's another column for another day.

So once a computer has been enabled for remote management, there are two main ways in which you can connect to that system from PowerShell. The first option is to run a one-off command (or set of commands). For that approach, you would need to enter something like this:

$Cred = Get-Credential
Invoke-Command <computer name>  -ScriptBlock {<commands to execute remotely>} -Credential $Cred

The first line of code shown above causes Windows to display a prompt asking for administrative credentials. Those credentials are then mapped to a variable called $Cred.

The second line of code uses a cmdlet called Invoke-Command to run a single command (or group of pipelined commands) against a specified remote system. In this command, <computername> would be replaced by the name or the IP address of the remote system. Similarly, the ScriptBlock section would contain the command or commands that you want to run remotely.

At the very end of the Invoke-Command cmdlet, we are using the -Credential parameter and the $Cred variable to supply administrative credentials that allow the command within the script block to be executed on the remote system.

The other way that remote management is commonly done through PowerShell involves using a remote session. A remote session connects to the remote machine, and every subsequent command that you enter executes on that machine. Hence, there is no need to try to cram everything into a script block. To create a remote session, use these commands:

$Cred =  Get-Credential
Enter-PSSession -ComputerName <computer name>  -Credential $Cred

Once again, we are mapping a set of administrative credentials to a variable. We are then entering the Enter-PSSession command and supplying the command with the name of the computer that we want to attach to and the administrative credentials for that machine.

PowerShell Direct
As previously noted, Microsoft makes things easier if you want to use PowerShell to manage a Hyper-V VM. As long as you are running an administrative PowerShell session from within the Hyper-V host operating system, you can connect to VMs that are running on that host with almost  no effort. You don't have to worry about setting up firewall exceptions, enabling PowerShell remoting or even supplying administrative credentials. You just connect, and that's it.

PowerShell Direct still uses the Enter-PSSession and Invoke-Command cmdlets that I showed you earlier, but the syntax is greatly simplified. If you want to use Invoke-Command to run a command on a VM, you can use this command:

Invoke-Command  -VMName <virtual machine name> -ScriptBlock {<commands to execute  remotely>}

Similarly, if you want to establish a session with a VM, you can use this command:

Enter-PSSession  -VMName <Virtual Machine Name>

Notice that in both cases, we simply supplied the VM name. There was no need for us to provide a set of administrative credentials, nor do we have to use the Enable-PSRemoting command within the VM before we can manage it from the host.

About the Author

Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.


comments powered by Disqus

Subscribe on YouTube