Design a site like this with WordPress.com
Get started

REVISE: Hyper-V Remote Management Using Powershell

Question: remote management powershell

PowerShell Remoting is Secure

 PowerShell Enables Any Version of Windows to Remotely Manage Any Other Version of Windows (and Hyper-V)

A very common complaint, and sometimes an outright problem, is that Hyper-V Manager can only fully control versions of Hyper-V that are running on the same code base. Hyper-V Manager in Windows 7 can’t control anything after the version of Hyper-V that released with the Windows 7/Windows Server 2008 R2 code base. Windows 8 or later was required. Starting in Windows 8/Server 2012, Hyper-V Manager can usually manage down-level hosts, but some people have troubles even with that.

With PowerShell, there’s no problem. PowerShell Remoting was introduced in PowerShell 2.0, and since then, PowerShell Remoting has worked perfectly well both up-level and down-level. The following is a screenshot of a Windows 7 installation with native PowerShell 2.0 remotely controlling a Hyper-V 2012 R2 server with native PowerShell 4.0:

PSRemoting Different Versions

PSRemoting Different Versions

How to Enable PowerShell Remoting for Hyper-V

Both the local and remote systems must be set up properly for PowerShell Remoting to work. The first thing that you must do on both sides is:

1Enable-PSRemoting -Force

On non-domain-joined systems, I received an “Access Denied” error unless I used the real Administrator account; just using an account in the local administrators group wasn’t enough. This seems to be at odds with the normal Windows authentication model and was just plain annoying for Windows 7, which disables the Administrator account by default. You can try the SkipProfileCheck parameter… it might help.

Installing the PowerShell Hyper-V Module

Not surprisingly, the easiest way to install the Hyper-V PowerShell module is with PowerShell. This works on Windows 8 and later, Windows Server 2012 and later, and Hyper-V Server 2012 and later:

1Install-WindowsFeature Hyper-V-PowerShell

If you’d like to install Hyper-V Manager along with the PowerShell module:

1Install-WindowsFeature RSAT-Hyper-V-Tools

If you’d like to install both of these tools along with Hyper-V:

1Install-WindowsFeature Hyper-V -IncludeManagementTools

If you’d rather take the long way through the GUI for some reason, your approach depends on whether or not you’re using a desktop or a server operating system.

For a desktop, open Turn windows features on or off via the Control Panel. Open the Hyper-V tree, then the Hyper-V Management Tools subtree, and check Hyper-V Module for Windows PowerShell (along with anything else that you’d like).

Hyper-V PowerShell Module on Windows

Hyper-V PowerShell Module on Windows

For a Server operating system, start in Server Manager. Click Add roles and features. Click through all of the screens in the wizard until you reach the Features page. Expand Remote Server Administration Tools, then Hyper-V Management Tools, and check Hyper-V Module for Windows PowerShell (along with anything else that you’d like).

Server Hyper-V PowerShell Module

Server Hyper-V PowerShell Module

Once the module is installed, you can use it immediately without rebooting. You might need to import it if you’ve already got an open PowerShell session, or you could just start a new session.

Implicit PowerShell Remoting in the Hyper-V Module

The easiest way to start using PowerShell Remoting is with implicit remoting. As a general rule, cmdlets with a ComputerName parameter are making use of implicit remoting. What that means is that all of the typing is done on your local machine, but all of the action occurs on the remote machine. Everything that the Hyper-V module does is in WMI, so this means that all of the commands that you type are being sent to the VMMS service on the target host to perform. If you are carrying this out interactively, the results are then returned to your console in serializedform.

To make use of implicit remoting with the Hyper-V module, you must have it installed on your local computer. There are more limitations on implicit remoting:

  • You can only (legally) install the Hyper-V PowerShell module that matches your local Windows version
  • You are limited to the functionality exposed by your local Hyper-V PowerShell module
  • No matter the local version, it cannot be used to manage 2008 R2 or lower target hosts
  • Implicit remoting doesn’t always work if the local and remote Hyper-V versions are different

For example, I cannot install the Hyper-V PowerShell module at all on Windows 7. As another example, the Hyper-V PowerShell module in Windows 10 cannot control a 2012 R2 environment. Basically, the Hyper-V PowerShell module on your local system follows similar rules as Hyper-V Manager on your local system. I want to reiterate that these rules only apply to implicit remoting; you can still explicitly operate any cmdlet in any module that exists on the target.

For example, from my Windows 10 desktop, I run Get-VM -CompterName svhv01 against my Windows Server 2016 TP5 host:

Implicit Remote Get-VM

Implicit Remote Get-VM

Behind the scenes, it is directing WMI on SVHV01 to run “SELECT * FROM Msvm_ComputerSystem” against its “root\virtualization\v2” namespace. It is then processing the results through a local view filter.

Implicit Remoting Against Several Hosts

I was saying how PowerShell Remoting can be used against multiple machines at once. Any time that a cmdlet’s ComputerName parameter supports a string array, you can operate it against multiple machines. Run Get-Help against the cmdlet in question and check to see if the ComputerName parameter has square brackets:

ComputerName with Array Support

ComputerName with Array Support

As you can see, Get-VM has square brackets in its ComputerName parameter (the [<String[]>]] part), so it can accept multiple hosts. Example:

1Get-VM -ComputerName svhv01, svhv02

Locking Implicit Remoting to a Specific Host

I have a complex environment with several hosts, so I am content to always specify the -ComputerName parameter as necessary. If you’ve only got a single host, then you might like to avoid typing that ComputerName parameter each time. To do that, open up your PowerShell profile and enter the following:

123Get-Command –Module Hyper-V –Verb Get | foreach { $PSDefaultParameterValues.Add(“$($_.Name):ComputerName”,”TARGETHOSTNAME”)}

Just replace TARGETHOSTNAME with the name or IP address of your remote host. From that point onward, any time you open any PowerShell prompt using the modified profile, all cmdlets from the Hyper-V module that start with “Get” will be automatically injected with “-ComputerName TARGETHOSTNAME”.

Implicit Remoting and the Pipeline

It can take some time and practice to become accustomed to how the pipeline works with implicit remoting, not least of which because some cmdlets behave differently. As a general rule, the pipeline brings items back to your computer.

So, let’s say you did this:

1Get-VM -ComputerName | Export-CSV -Path d:\temp\svhv02VMList.csv -NoTypeInformation

Where do you expect to find the file? On the remote host or the local host?

Implicit Remoting with a Pipeline

Implicit Remoting with a Pipeline

The file was created on my local system (if you looked closely at my screenshot and it made you curious, the file is zero length because there are no VMs on that system, not because it failed).

So, what this behavior means to you is that if you choose to then carry out operations on the objects such as Set cmdlets, you might need to use implicit remoting again after a pipeline… but then again, you might not. Which of the following do you think is correct?

  1. 1Get-VM -ComputerName svhv01 | Set-VMMemory -MaximumBytes 2.5GB
  2. 1Get-VM -ComputerName svhv01 | Set-VMMemory -ComputerName svhv01 -MaximumBytes 2.5GB

If you said #1, then you’re right! But, do you know why? It’s actually fairly simple to tell. Just look at the object that is crossing the pipeline:

Computer Name on Object

Computer Name on Object

The object contains its computer name and the cmdlets in the Hyper-V module are smart enough to process it as an object that contains a computer name. To then specify the computer name again for the cmdlet to the right of the pipeline just confuses PowerShell and causes it to error. Not all objects have a ComputerName property and not all cmdlets know to look for it. Furthermore, if you do anything to strip away that property and then try to pipe it to another cmdlet, you will need to specify ComputerName again. For example:

1Get-VM -ComputerName svhv01 | select Name | % { Set-VMMemory -ComputerName svhv01 -MaximumBytes 2.5GB -VMName $_.Name }

Explicit Remoting

If the remote host has the PowerShell module installed, you can establish a session to it and begin work immediately. Natively, this requires the target system to be 2012 or later, as there was no official Hyper-V PowerShell module in prior versions. There is an unofficial release for 2008 R2 (and maybe 2008, I never tried). Explicit remoting is “harder” than implicit remoting (requires more typing) but is much more powerful and there are no fancy rules governing it. If you can connect to the remote machine using PowerShell Remoting, then you can operate any PowerShell cmdlets there (for the PowerShell experts, just imagine that there is an asterisk right here that links to a mention of Constrained Endpoints).

There are two general ways to use explicit remoting. The first is to use Enter-PSSession. That drops you right onto the remote console as a sort of console-within-a-console. From there, you can work interactively. The second method is to encapsulate script in a block and feed it to Invoke-Command. That method is used for scripting and automatically cleans up after itself.

PowerShell Remoting in an Interactive Session

The simplest way to remotely connect to an interactive PowerShell session is:

1Enter-PSSession hostname

As shown, the command only works between machines on the same domain and when the current user account has sufficient privileges. I showed this above, but for the sake of completeness, to connect when one of the computers is unjoined or untrusted and/or if the user account is not administrative:

1Enter-PSSession hostname -Credential (Get-Credential)

This will securely prompt you for the credentials to use on the target. If the target is domained-joined, make sure you use the format of domain\username. If it’s a standalone system, you can use the username by itself or computername\username.

If the remote system is using SSL:

1Enter-PSSession hostname -Credential (Get-Credential) -UseSSL

Once the connection is established, it will change the prompt to reflect that you’re accessing the remote computer. You can see examples in the screenshots above. It will look like this:

1[hostname]: PS C:\Users\UserAccount\Documents>

One thing I generally avoid in instructional text is using positional parameters. I especially dislike mixing positional and named parameters. I’ve done both here for the sake of showing you how uncomplicated PowerShell Remoting is to use. For the purposes of delivering a proper education, be aware that the named parameter that you use to specify the host name is -ComputerName . As long as it’s the first parameter submitted to the cmdlet, you don’t have to type it out.

Once you’re connected, it’s mostly like you were sitting at a PowerShell prompt on the remote system. Be aware that any custom PowerShell profile you have on that host isn’t loaded. Also note that whatever you’re doing on that remote system stays on that system. For instance, you can’t put something into a variable and then call that variable from your system after you exit the session.

When you’re done, you can just close the PowerShell window. PowerShell will clean up for you. If you want to go back to working on your computer:

1Exit-PSSession

I much prefer the shorter alias:

1exit

Using PowerShell Remoting to Address the Remote Device Manager Problem

Now that you know how to connect to a remote PowerShell session, you have the ability to overcome one of the long-standing remote management challenges of both Windows and Hyper-V Server. Prior to the 2012 versions, you could remotely connect to Device Manager, but only in a read-only mode. Starting in 2012, even that is gone.

You can get driver information for a lot of devices using PowerShell. For example, Get-NetAdapter returns several Driver fields. But what about installing or upgrading drivers? That was never possible using Device Manager remotely, or even through other remote tools. Well, with PowerShell Remoting, the problem is solvable.

You’re not restricted to running PowerShell commands inside your remote session. You can run executables, batch files, and other such things. The only things you can’t do is initiate a GUI or start anything that has its own shell. Fortunately, one of the things that can be run is pnputil. This utility can be used to manage drivers on a system. So, with PowerShell Remoting, you can remotely install and upgrade drivers.

My systems use Broadcom NICs as their management adapters. I downloaded the drivers and transferred them into local drives on my hosts. Then, using PowerShell Remoting from my desktop, I connected in and used pnputil to install them. The command to install a driver is:

1pnputil -i -a driverfile.inf

You can see the results for yourself:

Remote PNPUTIL Driver Installation

You can see that, as expected, my network connection was interrupted. What’s not shown is that PowerShell used a progress bar to show its automatic reconnection attempts. Once the driver was installed, the session automatically picked up right where it left off.

For verification, you can use pnputil -e :

Remote PNPUTIL Driver Enumeration

Windows replaces the original driver file name with OEM#, as you can see here, but it keeps the manufacturer name and the driver version and date. If you want further verification, you can also run Get-NetAdapter | fl Driver* .

Advanced PowerShell Remoting with Invoke-Command

Here’s where the fun begins. Where the remote session usage shown above is great for addressing immediate needs, the true power of PowerShell Remoting is in connecting to multiple machines. Invoke-Command is the tool of choice:

1Invoke-Command -ComputerName svhv1, svhv2 -ScriptBlock { Get-VM }

If you run the above on systems prior to 2016, the first thing you’ll likely notice is that there’s no prettification of the output. Get-VM usually looks like this:

Demo Get-VM

That’s because there’s a defined custom formatting view being applied. When an object crosses back to a source system across Invoke-Command , no view is applied. What you get is mostly the same thing you’d see if you piped it through  Format-List -Property *  (mostly seen as  | fl *  ).

At this point, it might not make any sense why we’re doing this. This is the same output that we got from the implicit remoting earlier, but it required more typing, and more to remember.

If you have any VMs, the above cmdlets produce a wall of text. Let’s slim it down a bit. From PowerShell 2.0 in Windows 7, I ran  Invoke-Command -Computer svhv1, svhv2 -Credential (Get-Credential) -UseSSL -ScriptBlock { Get-VM | select Name }. Here’s the output:

Get-VM through Invoke-Command

Running the same script block locally would have resulted in a table with just the name column. Here, I get three more: PSComputerName, RunspaceId, and PSShowComputerName. In PowerShell 3.0 and later, the PSShowComputerName column isn’t there anymore. The benefit here is that you can use these fields to sort the output by the system that sent it.

You can use  -HideComputer with  Invoke-Command  to suppress the output of all the extra fields if your source system is running PowerShell 3.0 or later. For PowerShell 2.0, RunspaceId is still shown but the others are hidden. They’re still there, so you can query against them. What’s nice about this is, if your system has the related module installed, then any custom formatting views will be applied just as if you were running inside a connected session:

Invoked Get-VM with -HideComputerName

This formatting issue is no longer a concern in Windows 10/Windows Server 2016 (which I suspect is more due to changes in PowerShell 5 than in the Hyper-V module):

PowerShell Remoting Formatting in 2016

PowerShell Remoting Formatting in 2016

Being able to format the output will always be a useful skill even with the basic formatting issues automatically addressed.

It might not make sense why we’re doing things this way. The implicit remoting method that I showed you earlier did just as well, and it required less to type (and memorize). The first reason that you’d use this method is because it doesn’t matter if the local computer and the remote computer are running the same versions of anything. The PowerShell 2.0 examples on Windows 7 that I showed you were running against a Hyper-V Server 2012 R2 environment. Neither the Windows 7 nor my Windows 10 environment can even run implicit remoting against those systems.

Even more importantly, this doesn’t begin to show the true power of PowerShell Remoting. Let’s do some interesting things. For instance, looking at VM output is fun and all, but why stop there? How about:

$RemoteVMs = Invoke-Command -Computer svhv1, svhv2 -Credential (Get-Credential) -UseSSL -ScriptBlock { Get-VM }

What I’ve done here is connect in to both hosts, retrieve their virtual machines, store them in a variable on my computer, and then disconnected the remote session. I can store them, format the output, build reports, etc. What I can’t do is make any changes to them, but that’s OK. I’ve got a couple of answers to that.

First, I can perform the modifications right on the target system by using a more complicated script block. The following example builds a script that retrieves all the VMs that aren’t set to start automatically and sets them so that they do. That entire script is assigned to a variable named “RemoteVMManipulation”. I use that as the  -ScriptBlock parameter in an Invoke-Command , which I send to each of the hosts. The result of the script is saved to a variable:

123456789$RemoteVMManipulationBlock = {    $VMsNotStartingAutomatically = Get-VM | where { $_.AutomaticStartAction -ne “Start” }    foreach ($VM in $VMsNotStartingAutomatically)    {        Set-VM -VM $VM -AutomaticStartAction Start    }    $VMsNotStartingAutomatically}$ModifiedVMs = Invoke-Command -ComputerName svhv1, svhv2 -ScriptBlock $RemoteVMManipulationBlock

This isn’t the most efficient script block, but I wrote it that way for illustration purposes. The variable “VMsNotStartingAutomatically” is created on each of the remote systems, but is destroyed as soon as the script block exits. It is not retrievable or usable on my calling system. However, I’ve placed the combined output into a variable named “ModifiedVMs”. Like a local function call, the output is populated by whatever was in the pipeline at the end of the script block’s execution. In this case, it’s the “VMsNotStartingAutomatically” array. Upon return, this array is transferred to the “ModifiedVMs” variable, which lives only on my system. In subsequent lines of the above script, I can view the VM objects that were changed even though the remote sessions are closed.

The second way to manipulate the objects that were returned is to transmit them back to the remote hosts using the -InputObject  parameter and keep track of them with the added “PSComputerName” field:

12345678910111213$RemoteVMManipulationBlock = {    foreach ($VMList in $input)    {        foreach($VM in $VMList)        {            if($VM.PSComputerName -eq $env:COMPUTERNAME)            {                Set-VM -VMName $VM.Name -AutomaticStartAction StartIfRunning            }        }    }}Invoke-Command -ComputerName svhv1, svhv2 -ScriptBlock $RemoteVMManipulationBlock -InputObject $ModifiedVMs

What I’ve done here is send the “ModifiedVMs” variable from my system into each of the target systems using the-InputObject parameter. Once inside the script block, you reference this variable with $input . There are a few things to note here. For one, you’ll notice that I had to unpack the “ModifiedVMs” variable two times. For another, I wasn’t able to reference the input items as VM objects. Instead, I had to point it to the names of the VMs. This is because we’re not sending in true VM objects. We’re sending in what we got. GetType() reveals them as:

1Deserialized.Microsoft.HyperV.PowerShell.VirtualMachine

Because they’re a different object type, parameters expecting an object of the type “Microsoft.HyperV.PowerShell.VirtualMachine” will not work. Objects returned from Invoke-Command are always deserialized, which is why you have to go through these extra steps to do anything other than look at them. If you’ve got decent programming experience or you just don’t care about these sorts of things, you can skip ahead to the next section.

Serialization and deserialization are the methods that the .Net Framework, which is the underpinning of PowerShell, uses to first package objects for uses other than in-memory operations, and then to unpackage them later. There are lots of definitions out there for the term “object” in computer programming, but they are basically just containers. These containers hold only two things: memory addresses and an index of those memory addresses. The contents at those memory addresses are really just plain old binary 0s and 1s. It’s the indexes that give them meaning. How exactly that’s done from the developer’s view is dependent upon the language. So, in C++, you might find a “variable” defined as “int32”. This means that the memory location referenced by the index is 32 bits in length and the contents of those 32 bits should be considered an integer and that those contents can be modified. Indexes come in two broad types: data and code. In (a perhaps overly simplistic description of) .Net, data indexes are properties and refer to constants and variables. Code indexes can be either methods or events, and refer to functions.

As long as the objects are in memory, all of this works pretty much as you’d expect. If you send a read or write operation to a data index, then the contents of memory that it points to are retrieved or changed, respectively. If you (or, for an event, the system) call on a code index, then the memory contents it refers to are processed as an instruction set.

What happens if you want to save the object, say to disk? Well, you probably don’t care about the memory locations. You just want their contents. As for the functions and events, those have no meaning once the object is stored. So, what has to happen is all the code portions need to be discarded and the names of the indexes need to be paired up with the contents of the memory that they point to. As mentioned earlier, the .Net Framework does this by a process called serialization. Once an object is serialized, it can be written directly to disk. In our case, though, the object is being transmitted back to the system that called Invoke-Command .  Once there, it is deserialized so that its new owning system can manipulate it in-memory like any other object. However, because it came from a serialized object, its structure looks different than the original because it isn’t the same object.

You’ll notice that all the events are gone. The only methods are GetType() and ToString(), which are part of this new object, not carried over from the original, and are here because they exist on every PowerShell object. Properties that contained complex objects have also been similarly serialized and deserialized.

Using Saved Credentials and Multiple Sessions

Of course, what puts the power into PowerShell is automation. Automation should mean you can “set it and forget it”. It’s tough to do that if you have to manually enter information into Get-Credential, isn’t it?

There’s also the problem of multiple credential sets. Hopefully, if you’ve got more than one host that sits outside your domain, they’ve each got their own credentials. I know that some people out there put Hyper-V systems in workgroup mode “to protect the domain” but then use a credential set with the same user name and password as their domain credentials. It’s no secret that I see no value in workgroup Hyper-V hosts when a domain is available except for perimeter networks, but if you’re going to do it, at least have the sense to use unique user names and passwords. Sure, it can be inconvenient, but when you actively choose the micro-management hell of workgroup-joined machines, you can’t really be surprised when you find yourself in micro-management hell. Fortunately for you, PowerShell Remoting can take a lot of the sting out of it.

The first step is to gather the necessary credentials for all of your remote machines and save them into disk files on the system where you’ll be running Invoke-Command. For that bit, I’m just going to pass the buck to Lee Holmes. He does a great job explaining both the mechanism and the safety of the process.

Once you have the credentials stored in variables, you next create individual sessions to the various hosts.

12$SVHV1Session = New-PSSession -ComputerName svhv1 -Credential $SVHV1Credential$SVHV2Session = New-PSSession -ComputerName svhv2 -Credential $SVHV2Credential

You’re all set. You use the sessions like this:

1$RemoteVMs = Invoke-Command -Session $SVHV1Session, $SVHV2Session -ScriptBlock { Get-VM }

Of course, if you’ve only got one remote host but you want to use credentials retrieved from disk, you don’t need the sessions:

1$RemoteVMs = Invoke-Command -ComputerName svhv1 -Credential $SVHV1Credential -ScriptBlock { Get-VM }

One thing to remember though, is that sessions created with New-PSSession will persist, even if you close your PowerShell prompt. They’ll eventually time out, but until then, they’re like a disconnected RDP session. They just sit there and chew up resources, giving an attackers an open session to attempt to compromise, all for no good reason. If you want, you can reconnect and reuse these sessions. Otherwise, get rid of them:

12$SVHV1Session | Remove-PSSession$SVHV2Session | Remove-PSSession

Or, to close all:

1Get-PSSession | Remove-PSSession

For More Information

I’ve really only scratched the surface of PowerShell Remoting here. I had heard about it some time before, but I wasn’t in a hurry to use it because I was “getting by” with Hyper-V Manager and Remote Desktop connections. Ever since I spent a few minutes learning about Remoting, I have come to use it every single day. The ad hoc capabilities of Enter-PSSession allow me to knock things out quickly and the scripting powers of Invoke-Command are completely irreplaceable.

All that, and I haven’t even talked about delegated administration (allowing a junior admin to carry out a set of activities as narrowly defined as you like via a pre-defined PowerShell Remoting session) or implicit remoting or setting up “second hop” powers so you can control other computers from within your remote session. For those things, and more, you’re going to have to do some research on your own. I recommend starting with PowerShell in Depth. Most of the general information, but not all, of what you saw in this article can be found in that book. That chapter does contain all the things I teased about, and more.

Question: VMs with PowerShell SCVMM or Hyper-V Manager

Hyper-V Manager, SCVMM and PowerShell can all be used to create a Hyper-V VM, but if you want to configure certain parameters beforehand, you need to use SCVMM.

There are several ways to create VMs on Hyper-V virtualization hosts. The standard approach is to use Hyper-V Manager or System Center Virtual Machine Manager. However, many administrators like to use PowerShell cmdlets to quickly provision Hyper-V VMs. PowerShell is a very useful tool for when you need to deploy Hyper-V VMs in a development environment or when you need to perform VM creation tasks repeatedly.

Create Hyper-V VMs using Hyper-V Manager

Most Hyper-V administrators are familiar with the VM creation process using Hyper-V Manager. All you need to do is open Hyper-V Manager, right-click on a Hyper-V host in the list of available hosts, click on the New action, click on the Virtual Machine action and then follow the steps on the screen to create the VM. You’ll need to specify parameters, like VM name, VM generation and the path to store VM files.

Create Hyper-V VMs using SCVMM

Deploying VMs using System Center Virtual Machine Manager (SCVMM) is fairly simple. You can deploy VMs on a standalone Hyper-V host or in a Hyper-V cluster. You need to go to the VMs and Services workspace, right-click on a SCVMM host group and then click on the Create Virtual Machine action

When you click on the Create Virtual Machine action, SCVMM will open a wizard. All you need to do is follow the steps on the screen. One of the main advantages of SCVMM is that it allows you to configure VM parameters — including Dynamic Memory — before the actual creation process starts. Another benefit of using SCVMM is that you can quickly provision a VM by selecting a SCVMM template that already includes the required VM settings. SCVMM also provides greater flexibility when deploying VMs in a production environment.

When you provision VMs using SCVMM, SCVMM creates a PowerShell script on the fly and then executes it via the SCVMM job window. If you need to use the PowerShell script where SCVMM isn’t installed, you can copy the PowerShell script from the SCVMM job window and modify the Hyper-V host-related parameters.

Create Hyper-V VMs using PowerShell

Hyper-V offers the New-VM PowerShell cmdlet that can be used to create a VM on a local or remote Hyper-V host. It’s important to note that, before creating Hyper-V VMs using PowerShell, you’ll need to make some configuration decisions, as explained below:

  • Figure out the Hyper-V virtual switch to which the VM will be connected. You can get Hyper-V virtual switch names by executing the Get-VMSwitch * | Format-Table NamePowerShell command. The command will list all the Hyper-V virtual switches on the local Hyper-V host. Copy the Hyper-V virtual switch name to be used in the VM creation command.
  • Decide the type of memory configuration for the new VM. Are you planning to use static memory or Dynamic Memory? If you plan to use the Dynamic Memory feature, you’ll need to use the Set-VMMemory PowerShell cmdlet after creating the VM.
  • Identify the VM file path where VM files will be stored. It can be a local path, a path to the Cluster Shared Volumes disk in the Hyper-V cluster or a path to the Scale-Out File Server cluster.
  • Decide if you’d like the OS in the VM to be installed via a Preboot Execution Environment server running on the network or if you’d like to set up the OS from a DVD. Depending on the OS deployment type, you’d want to change the boot order of the VM.
  • Are you going to create a new VM on a local or remote Hyper-V host? If you’re going to create a VM on a remote Hyper-V host, get the Hyper-V server’s fully qualified domain name or IP address, and specify that value using the -ComputerName parameter in the New-VMPowerShell cmdlet.
  • Choose the generation of the VM. Generation 2 VMs provide new features, such as guest clustering, Hyper-V virtual hard disk (VHDX) online resizing, secure boot, fast boot and so on. I recommend you choose Generation 2 unless you have a reason to go for Generation 1 VMs.

Once you have gathered the required parameters for the new VM, use the PowerShell command below to create the VM on the Hyper-V host.

New-VM –Name SQLVM –MemoryStartupBytes 8GB –BootDevice VHD –VHDPath C:\ProductionVMs\SQLVM.VHDX –Path C:\ProductionVMs\VMFiles –Generation 2 –Switch ProductionSwitch

This command will create a VM by the name of the SQLVM on the local Hyper-V host. The new VM will be configured to use 8 GB of memory and will be stored in the C:\ProductionVMs folder. Note that -Generation 2 specifies that this VM will be created as a Generation 2 VM. If you want to change the new VM’s memory configuration from static to Dynamic Memory, use the PowerShell command below:

Stop-VM –Name SQLVM

Set-VMMemory SQLVM –DynamicMemoryEnabled $True –MinimumBytes 250MB –StartupBytes 500MB –MaximumBytes 8GB –Priority 70 –Buffer 20

These commands configure the SQLVM with Dynamic Memory and set the required parameters for Dynamic Memory.

Question: run powershell commands against a remote vm

Here’s a look at the Invoke-Command cmdlet and how it will be extended in Windows Server 2016.

PowerShell is one of Microsoft’s preferred tools for managing Windows Servers. Although it’s easy to think of PowerShell as a local management tool, PowerShell can just as easily be used to manage other servers in your datacenter. This capability is especially helpful if you have a lot of Hyper-V virtual machines and want to be able to perform bulk management operations.

There are a few different ways of running a PowerShell command against a remote server. For the purposes of this article however, I want to show you how to use the Invoke-Command cmdlet. The reason why I want to talk about this particular method is because the Invoke-Command cmdlet is being extended in Windows Server 2016 to provide better support for Hyper-V virtual machines. I will get to that in a few minutes.

The first thing that you will need to do is to configure the remote system to allow for remote management. Microsoft disables remote PowerShell management by default as a way of enhancing security.

To enable remote PowerShell management, logon to the remote server, open PowerShell (as an Administrator) and run the following command:

Enable-PSRemoting –Force

This command does a few different things. First, it starts the WinRM service, which is used for Windows remote management. It also configures the service to start automatically each time that the server is booted and it also adds a firewall rule that allows inbound connections. In case you are wondering, the Force parameter is used for the sake of convenience. Without it, PowerShell will nag you for approval as it performs the various steps. You can see what the command looks like in action in Figure 1.

[Click on image for larger view.]  Figure 1. You must use the Enable-PSRemoting cmdlet to prepare the remote server for management.

There are about a zillion different ways that you can use the Invoke-Command cmdlet. Microsoft provides full documentation for using this cmdlet here. This site covers the full command syntax in ponderous detail. For the purposes of this article however, I want to try to keep things simple and show you an easy method of running a command against a remote system.

The first thing that you need to know is that any time you are going to be running a PowerShell command against a remote system, you will have to enter an authentication credential. Although this step is necessary, it is a bit of a pain to enter a set of credentials every time you run a command. Therefore, my advice is to map your credentials to a variable. To do so, enter the following command:

$Cred = Get-Credential

As you can see in Figure 2, entering this command causes PowerShell to prompt you for a username and password. The credentials that you enter are mapped to the variable $Cred.

[Click on image for larger view.]  Figure 2. Your credentials can be mapped to a variable.

Now that your credentials have been captured, the easiest way to run a command against a remote server is by using the following syntax:

Invoke-Command –ComputerName <server name> -Credential  $Cred –ScriptBlock{The command that you want to run}

OK, so let’s take a look at how this command works. Right now I am using PowerShell on a system that is running Windows 8.1. I have a Hyper-V server named Hyper-V-4. Let’s suppose that I want to run the Get-VM cmdlet on that server so that I can find out what virtual machines currently exist on it. To do so, I would use this command:

Invoke-Command –ComputerName Hyper-V-4 –Credential $Cred  –ScriptBlock{Get-VM}

As you can see, the script block contains the command that needs to be executed on the remote system. It is worth noting that this technique only works if both computers are domain joined and are using Kerberos authentication. Otherwise, you will have to use the HTTPS transport or add the remote computer to a list of trusted hosts. The previously mentioned TechNet article contains instructions for doing so.

At the beginning of this article, I mentioned that Invoke-Command was being extended in Windows Server 2016 to better support Hyper-V virtual machines. Microsoft is adding a parameter named VMName (which is used in place of ComputerName). This extension makes use of a new feature called PowerShell direct, which allows you to run PowerShell commands on a Hyper-V virtual machine even if the virtual machine is not connected to the network. This is accomplished by communicating with the VM through the VMBus.

So as you can see, the Invoke-Command cmdlet makes it easy to manage remote servers through PowerShell. I would encourage you to check out the previously mentioned TechNet article because there is a lot more that you can do with the Invoke-Command cmdlet than what I have covered here.

Question: managing hyper-v server remotely through powershell

Working with PowerShell can be very common for daily tasks and Hyper-V Server management. However, as there is more than one server to be managed, sometimes it can be difficult to log on and run the PowerShell scripts (most of the time the same one) on different computers.

One of the benefits that PowerShell offers is the remote option that allows you to connect to multiple servers, enabling a single PowerShell window to administer as many servers as you need.

The PowerShell remote connection uses port 80, HTTP. Although the local firewall exception is created by default when it’s enabled, make sure that any other firewall has the exception to allow communication between your servers.

How to do it

These tasks will show you how to enable the PowerShell Remoting feature to manage your Hyper-V Servers remotely using PowerShell.

1. Open a PowerShell window as an administrator from the server for which you want to enable the PowerShell Remoting.

2. Type the Enable-PSRemoting commandlet to enable PowerShell Remoting.

3. The system will prompt you to confirm some settings during the setup. Select A for Yes to All to confirm all of them. Run the Enable-PSRemoting command on all the servers that you want to connect to remotely via PowerShell.

4. In order to connect to another computer in which the PowerShell Remoting is already enabled, type Connect-PSSession Hostname, where hostname is the computer name to which you want to connect.

5. To identify all the commands used to manage the PowerShell sessions, you can create a filter with the command Get-Command *PSSession*. A list of all the PSSession commands will appear, showing you all the available remote connection commands.

6. To identify which command lines from Hyper-V can be used with the remote option computername, use the Get-Commandwith the following parameter:

Get-Command –Module Hyper-V –ParameterName Computername

7. To use the remote PowerShell connection from PowerShell ISE, click on File and select New Remote PowerShell Tab. A window will prompt you for the computer name to which you want to connect and the username, as shown in the following screenshot. Type the computer name and the username to create the connection and click on Connect. Make sure that the destination computer also has the remoting settings enabled.

clip_image002

8. A new tab with the computer name to which you have connected will appear at the top, identifying all the remote connections that you have through PowerShell ISE. The following screenshot shows an example of a PowerShell ISE window with two tabs. The first one to identify the local connection called PowerShell 1 and the remote computer tab called HVHost.

clip_image004

Summary

The process to enable PowerShell involves the creation of a firewall exception, WinRM service configuration, and the creation of a new listener to accept requests from any IP address. PowerShell configures all these settings through a single and easy command—Enable-PSRemoting. By running this command, you will make sure that your computer has all the components enabled and configured to accept and create new remote connections using PowerShell.

Then, we identified the commands which can be used to manage the remote connections. Basically, all the commands that contain PSSession in them. Some examples are as follows:

· Connect-PSSession to create and connect to a remote connection

· Enter-PSSession to connect to an existing remote connection

· Exit-PSSession to leave the current connection

· Get-PSSession to show all existing connections

· New-PSSession to create a new session

Another interesting option that is very important, is to identify which commands support remote connections. All of them use the ComputerName switch. To show how this switch works, see the following example; a command to create a new VM is being used to create a VM on a remote computer named HVHost.

New-VM –Name VM01 –ComputerName HVHost

To identify which commands support the Computername switch, you saw the Get-Command being used with a filter to find all the commandlets. After these steps, your servers will be ready to receive and create remote connections through PowerShell.

Question: 12 steps to remotely manage hyper-v server 2012 core

Here are 12 steps to remotely manage Hyper-V Server 2012 Core. Have you setup a Microsoft Hyper-V Server 2012 Core edition and now you want to remotely manage it in a workgroup (non-domain) environment?

Hopefully I can help ease your frustration with this article by showing you what worked for me.

If Microsoft did one thing that really tested my patients it’s trying to remotely manage Hyper-V Server Core in a workgroup environment.

Not long ago, I wrote an article titled Remotely Mange Hyper-V Server 2012 Core but admit I lost steam with wanting to work with it after that article/video. I wasn’t very confident with those instructions because every time I tested it there seemed to be different results.

Earlier today I decided to tackle this one again because I have had a lot of questions on this topic. It appears a lot of you out there are having similar issues. I feel very confident this time that I have all the instructions tested and working.

12 Steps to Remotely Manage Hyper-V

Quick run-down

  • Server: Microsoft Hyper-V Server 2012 Core (Free Edition)
  • Client: Windows 8 Pro

This next section is what I’m calling the condensed (advanced) version.

Condensed (advanced) Version

Install Hyper-V Server 2012 Core and log in to the console.

  1. Configure date and time (select #9).
  2. Enable Remote Desktop (select #7). Also select the ‘Less Secure’ option.
  3. Configure Remote Management (select #4 then #1).
  4. Add local administrator account (select #3). Username and password need to be exactly the same as the account you are going to use on the client computer to manage this Hyper-V Server.
  5. Configure network settings (select #8). Configure as a static IP. Same subnet as your home network. Don’t forget to configure the DNS IP.
  6. Set the computer name (select #2). Rename the server and reboot.
  7. Remote Desktop to server. On your client machine, remote to the server via the IP address you assigned it. Use the credentials of the local administrator account you created earlier.
  8. Launch PowerShell. In the black cmd window, run the following command: start powershell
  9. Run the following commands:
    • Enable-NetFirewallRule -DisplayGroup “Windows Remote Management”
    • Enable-NetFirewallRule -DisplayGroup “Remote Event Log Management”
    • Enable-NetFirewallRule -DisplayGroup “Remote Volume Management”
    • Set-Service VDS -StartupType Automatic
  10. Reboot the server (select #12).
  11. Enable Client Firewall Rule. On your client machine, launch an elevated PowerShell prompt and type the following command:
    • Enable-NetFirewallRule -DisplayGroup “Remote Volume Management”
    • ii c:\windows\system32\drivers\etc
  12. Add server hostname and IP to hosts file. Right click hosts and select properties. In the security tab, add your username. Give your account modify rights.This is needed because some remote management tools we need to use rely on the hosts file to resolve the name. Without doing this you are highly likely to encounter some errors while trying to create VHDs and such. Error you might see: There was an unexpected error in configuring the hard disk.

There you have it: 12 steps to remotely manage Hyper-V Server 2012 Core.

You should now be able to remotely manage the Hyper-V server from the client machine. This includes managing the Hyper-V server’s disk from within the disk management console on the client. You should be able to create VHD’s successfully as well from within Hyper-V Manager on the client (assuming you installed the feature).

This was a quick tutorial on how to setup a working Hyper-V Server 2012 Core edition in a non-domain (workgroup) environment and still be able to remotely manage it.