Connecting to Hyper-V virtual machines with PowerShell
I’ve been using Windows 8 since its pre-release versions and one of the features I like most in it is – Hyper-V. Until Windows 8, Hyper-V was available only as a Server technology. Starting with Windows 8, it is now available out of the box!
In a nutshell, Hyper-V lets you run more than one 32-bit or 64-bit operating system at the same time on the same computer. In Windows 8, this technology is now built into the non-server version of Windows. Client Hyper-V provides the same virtualization capabilities as Hyper-V in Windows Server 2012.
For us, IT Pros, having a virtualized environment nowadays is almost a necessity as many of us need to run multiple operating systems, and maintain multiple test environments. Hyper-V is an optional feature. You must first enable it.
Note: Client Hyper-V is supported only on 64-bit versions of Windows 8, Pro or Enterprise, having at least 4 GB of RAM, and requires modern Intel and AMD microprocessors that include Second Level Address Translation (SLAT) technologies.
Enable Hyper-V using the UI
On the Control Panel, click Programs, and then click Programs and Features, click ‘Turn Windows features on or off’, tick the Hyper-V checkbox , click OK, and then click Close.
Enable Client Hyper-V using Windows PowerShell
Open Windows PowerShell and type the following command (which is a part of the Dism module):
Enable-WindowsOptionalFeature –FeatureName Microsoft-Hyper-V -All
To complete installation you need to restart your computer. After restarting the computer, you can use Hyper-V Manager or Windows PowerShell to create and manage virtual machines. You can also use Virtual Machine Connection (vmc) to connect to virtual machines locally or remotely.
Connecting to Virtual Machines
You can connect to your VMs by using the Virtual Machine Connection utility. Notice the warning at the bottom of the dialog. I launched it without administrative privileges and as a result I won’t be able to connect to VMs. Make sure you right click it and open it as an administrator.
That warning is also valid when you use the Hyper-V cmdlets, and the error you get back is misleading; it doesn’t mention required permissions whatsoever. For example, if you run the Get-VM from a non-elevated console:
PS> Get-VM -VMName DC12
Get-VM :The parameter is not valid. Hyper-V was unable to find a virtual machine with name DC12.
At line:1 char:1
+ Get-VM -VMName DC12
+ CategoryInfo : InvalidArgument: (DC12:String) [Get-VM], VirtualizationInvalidArgumentException
+ FullyQualifiedErrorId : InvalidParameter,Microsoft.HyperV.PowerShell.Commands.GetVMCommand
Alternatively, you can use the Hyper-V Manager. Just right click a VM and then ‘Connect’:
The Hyper-V module for Windows PowerShell
The Hyper-V module for Windows PowerShell includes more than 160 cmdlets to manage Hyper-V virtual machines. The cmdlets provide an easy way to automate Hyper-V management tasks. Here’s a partial list of the module commands:
PS> Get-Command -Module Hyper-V CommandType Name ModuleName ----------- ---- ---------- Cmdlet Add-VMDvdDrive hyper-v Cmdlet Add-VMFibreChannelHba hyper-v Cmdlet Add-VMHardDiskDrive hyper-v Cmdlet Add-VMMigrationNetwork hyper-v Cmdlet Add-VMNetworkAdapter hyper-v Cmdlet Add-VMNetworkAdapterAcl hyper-v Cmdlet Add-VMRemoteFx3dVideoAdapter hyper-v Cmdlet Add-VMScsiController hyper-v Cmdlet Add-VMStoragePath hyper-v Cmdlet Add-VMSwitch hyper-v Cmdlet Add-VMSwitchExtensionPortFeature hyper-v Cmdlet Add-VMSwitchExtensionSwitchFeature hyper-v Cmdlet Checkpoint-VM hyper-v Cmdlet Compare-VM hyper-v Cmdlet Complete-VMFailover hyper-v Cmdlet Connect-VMNetworkAdapter hyper-v Cmdlet Connect-VMSan hyper-v Cmdlet Convert-VHD hyper-v Cmdlet Disable-VMEventing hyper-v (...)
The online reference of the Hyper-V cmdlets in Windows PowerShell can be found here: http://technet.microsoft.com/library/hh848559.aspx
One of the first things I’ve tried when working with Hyper-V was to connect to a VM via PowerShell but I couldn’t find a Connect-VM cmdlet!
Under the hood, Hyper-V Manager is using the vmc utility (vmconnect.exe) to connect to a VM.
Based on the parameters of vmc, I created the Connect-VM advanced function. With Connect-VM, you can connect to a VM, locally or on a remote machine and even start it, if it isn’t already running. You can pipe VMs you get with Get-VM to it or just specify the VM name(s) or GUIDs. And with a few modifications you can also extend it to launch Remote Desktop instead of Hyper-V.
#requires -Version 3.0
function Connect-VM
{
[CmdletBinding(DefaultParameterSetName='name')]
param(
[Parameter(ParameterSetName='name')]
[Alias('cn')]
[System.String[]]$ComputerName=$env:COMPUTERNAME,
[Parameter(Position=0,
Mandatory,ValueFromPipelineByPropertyName,
ValueFromPipeline,ParameterSetName='name')]
[Alias('VMName')]
[System.String]$Name,
[Parameter(Position=0,
Mandatory,ValueFromPipelineByPropertyName,
ValueFromPipeline,ParameterSetName='id')]
[Alias('VMId','Guid')]
[System.Guid]$Id,
[Parameter(Position=0,Mandatory,
ValueFromPipeline,ParameterSetName='inputObject')]
[Microsoft.HyperV.PowerShell.VirtualMachine]$InputObject,
[switch]$StartVM
)
begin
{
Write-Verbose "Initializing InstanceCount, InstanceCount = 0"
$InstanceCount=0
}
process
{
try
{
foreach($computer in $ComputerName)
{
Write-Verbose "ParameterSetName is '$($PSCmdlet.ParameterSetName)'"
if($PSCmdlet.ParameterSetName -eq 'name')
{
# Get the VM by Id if Name can convert to a guid
if($Name -as [guid])
{
Write-Verbose "Incoming value can cast to guid"
$vm = Get-VM -Id $Name -ErrorAction SilentlyContinue
}
else
{
$vm = Get-VM -Name $Name -ErrorAction SilentlyContinue
}
}
elseif($PSCmdlet.ParameterSetName -eq 'id')
{
$vm = Get-VM -Id $Id -ErrorAction SilentlyContinue
}
else
{
$vm = $InputObject
}
if($vm)
{
Write-Verbose "Executing 'vmconnect.exe $computer $($vm.Name) -G $($vm.Id) -C $InstanceCount'"
vmconnect.exe $computer $vm.Name -G $vm.Id -C $InstanceCount
}
else
{
Write-Verbose "Cannot find vm: '$Name'"
}
if($StartVM -and $vm)
{
if($vm.State -eq 'off')
{
Write-Verbose "StartVM was specified and VM state is 'off'. Starting VM '$($vm.Name)'"
Start-VM -VM $vm
}
else
{
Write-Verbose "Starting VM '$($vm.Name)'. Skipping, VM is not not in 'off' state."
}
}
$InstanceCount+=1
Write-Verbose "InstanceCount = $InstanceCount"
}
}
catch
{
Write-Error $_
}
}
}
Usage examples
# Connect to VM and start it
PS> Connect-VM -VMName DC12 -StartVM
- Connecting to multiple VMs, when multiple connections are made the windows are cascaded. Without it they would sit on top of each other at the same position making it hard to switch from one to another.
PS> Get-VM | Connect-VM
- Connect using a VM’s Guid
PS> Connect-VM -Id 34d22d46-15c7-4226-9fa2-04f6c90a5a9a -StartVM
You can download the function HERE
Share on: