REVISE: WinRM and PSRemoting

Enable-PSRemoting

Enable-PSRemoting

This command configures the computer to receive remote commands.

The Enable-PSRemoting cmdlet configures the computer to receive Windows PowerShell remote commands that are sent.

to enable Windows PowerShell remoting on other supported versions of Windows

You need to run this command only once on each computer that will receive commands. You do not need to run it on computers that only send commands. Because the configuration activates listeners, it is prudent to run it only where it is needed.

To run this cmdlet, start Windows PowerShell with the “Run as administrator” option.

CAUTION: On systems that have both Windows PowerShell 3.0 and the Windows PowerShell 2.0 engine, do not use Windows PowerShell 2.0 to run the Enable-PSRemoting and Disable-PSRemoting cmdlets. The commands might appear to succeed, but the remoting is not configured correctly. Remote commands, and later attempts to enable and disable remoting, are likely to fail.

  • In Windows PowerShell 3.0, Enable-PSRemoting creates the following firewall exceptions for WS-Management communications.On server versions of Windows, Enable-PSRemoting creates firewall rules for private and domain networks that allow remote access, and creates a firewall rule for public networks that allows remote access only from computers in the same local subnet.On client versions of Windows, Enable-PSRemoting in Windows PowerShell 3.0 creates firewall rules for private and domain networks that allow unrestricted remote access. To create a firewall rule for public networks that allows remote access from the same local subnet, use the SkipNetworkProfileCheckparameter.On client or server versions of Windows, to create a firewall rule for public networks that removes the local subnet restriction and allows remote access , use the Set-NetFirewallRule cmdlet in the NetSecurity module to run the following command: Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP-PUBLIC" -RemoteAddress Any
  • In Windows PowerShell 2.0, Enable-PSRemoting creates the following firewall exceptions for WS-Management communications.On server versions of Windows, it creates firewall rules for all networks that allow remote access.On client versions of Windows, Enable-PSRemoting in Windows PowerShell 2.0 creates a firewall exception only for domain and private network locations. To minimize security risks, Enable-PSRemoting does not create a firewall rule for public networks on client versions of Windows. When the current network location is public, Enable-PSRemoting returns the following message: “Unable to check the status of the firewall.”
  • Beginning in Windows PowerShell 3.0, Enable-PSRemoting enables all session configurations by setting the value of the Enabled property of all session configurations (WSMan:\<ComputerName>\Plugin\<SessionConfigurationName>\Enabled) to True ($true).
  • In Windows PowerShell 2.0, Enable-PSRemoting removes the Deny_All setting from the security descriptor of session configurations. In Windows PowerShell 3.0, Enable-PSRemoting removes the Deny_All and Network_Deny_All settings, thereby providing remote access to session configurations that were reserved for local use.
Enable-PSRemoting -Force

This command configures the computer to receive remote commands. It uses the Force parameter to suppress the user prompts.

Enable-PSRemoting -SkipNetworkProfileCheck -Force

Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP-PUBLIC" -RemoteAddress Any

This example shows how to allow remote access from public networks on client versions of Windows. Before using these commands, analyze the security setting and verify that the computer network will be safe from harm.

The first command enables remoting in Windows PowerShell. By default, this creates network rules that allow remote access from private and domain networks. The command uses the SkipNetworkProfileCheckparameter to allow remote access from public networks in the same local subnet. The command uses the Force parameter to suppress confirmation messages.

The SkipNetworkProfileCheck parameter has no effect on server version of Windows, which allow remote access from public networks in the same local subnet by default.

The second command eliminates the subnet restriction. The command uses the Set-NetFirewallRule cmdlet in the NetSecurity module to add a firewall rule that allows remote access from public networks from any remote location, including locations in different subnets.

-SkipNetworkProfileCheck

Enables remoting on client versions of Windows when the computer is on a public network. This parameter enables a firewall rule for public networks that allows remote access only from computers in the same local subnet.

This parameter has no effect on server versions of Windows, which, by default, have a local subnet firewall rule for public networks. If the local subnet firewall rule is disabled on a server version of Windows, Enable-PSRemoting re-enables it, regardless of the value of this parameter.

To remove the local subnet restriction and enable remote access from all locations on public networks, use the Set-NetFirewallRule cmdlet in the NetSecurity module.

How to Run PowerShell Commands on Remote Computers

PowerShell Remoting lets you run PowerShell commands or access full PowerShell sessions on remote Windows systems. It’s similar to SSH for accessing remote terminals on other operating systems.

PowerShell is locked-down by default, so you’ll have to enable PowerShell Remoting before using it. This setup process is a bit more complex if you’re using a workgroup instead of a domain—for example, on a home network—but we’ll walk you through it.

Enable PowerShell Remoting on the PC You Want to Access Remotely

Your first step is to enable PowerShell Remoting on the PC to which you want to make remote connections. On that PC, you’ll need to open PowerShell with administrative privileges.

-In Windows 10, press Windows+X and then choose PowerShell (Admin) from the Power User menu.

-In Windows 7 or 8, hit Start, and then type “powershell.” Right-click the result and choose “Run as administrator.”

-In the PowerShell window, type the following cmdlet (PowerShell’s name for a command), and then hit Enter:

Enable-PSRemoting -Force

This command starts the WinRM service, sets it to start automatically with your system, and creates a firewall rule that allows incoming connections. The -Force part of the cmdlet tells PowerShell to perform these actions without prompting you for each step.

If your PCs are part of a domain, that’s all the setup you have to do. You can skip on ahead to testing your connection. If your computers are part of a workgroup—which they probably are on a home or small business network—you have a bit more setup work to do.

Note: Your success in setting up remoting in a domain environment depends entirely on your network’s setup. Remoting might be disabled—or even enabled—automatically by group policy configured by an admin. You might also not have the permissions you need to run PowerShell as an administrator. As always, check with your admins before you try anything like this. They might have good reasons for not allowing the practice, or they might be willing to set it up for you.

Set Up Your Workgroup

If your computers aren’t on a domain, you need to perform a few more steps to get things set up. You should have already enabled Remoting on the PC to which you want to connect, as we described in the previous section.

Note: For PowerShell Remoting to work in a workgroup environment, you must configure your network as a private, not public, network.

Next, you need to configure the TrustedHosts setting on both the PC to which you want to connect and the PC (or PCs) you want to connect from, so the computers will trust each other. You can do this in one of two ways.

If you’re on a home network where you want to go ahead and trust any PC to connect remotely, you can type the following cmdlet in PowerShell (again, you’ll need to run it as Administrator).

Set-Item wsman:\localhost\client\trustedhosts *

The asterisk is a wildcard symbol for all PCs. If instead you want to restrict computers that can connect, you can replace the asterisk with a comma-separated list of IP addresses or computer names for approved PCs.

After running that command, you’ll need to restart the WinRM service so your new settings take effect. Type the following cmdlet and then hit Enter:

Restart-Service WinRM

And remember, you’ll need to run those two cmdlets on the PC to which you want to connect, as well as on any PCs you want to connect from.

Test the Connection

Now that you’ve got your PCs set up for PowerShell Remoting, it’s time to test the connection. On the PC you want to access the remote system from, type the following cmdlet into PowerShell (replacing “COMPUTER” with the name or IP address of the remote PC), and then hit Enter:

Test-WsMan COMPUTER

This simple command tests whether the WinRM service is running on the remote PC. If it completes successfully, you’ll see information about the remote computer’s WinRM service in the window—signifying that WinRM is enabled and your PC can communicate. If the command fails, you’ll see an error message instead.

Execute a Single Remote Command

To run a command on the remote system, use the Invoke-Command cmdlet using the following syntax:

Invoke-Command -ComputerName COMPUTER -ScriptBlock { COMMAND } -credential USERNAME

“COMPUTER” represents the remote PC’s name or IP address. “COMMAND” is the command you want to run. “USERNAME” is the username you want to run the command as on the remote computer. You’ll be prompted to enter a password for the username.

Here’s an example. I want to view the contents of the C:\ directory on a remote computer with the IP address 10.0.0.22. I want to use the username “wjgle,” so I would use the following command:

Invoke-Command -ComputerName 10.0.0.22 -ScriptBlock { Get-ChildItem C:\ } -credential wjgle

Start a Remote Session

If you have several cmdlets you want to run on the remote PC, instead of repeatedly typing the Invoke-Command cmdlet and the remote IP address, you can start a remote session instead. Just type the following cmdlet and then hit Enter:

Enter-PSSession -ComputerName COMPUTER -Credential USER

Again, replace “COMPUTER” with the name or IP address of the remote PC and replace “USER” with the name of the user account you want to invoke.

Your prompt changes to indicate the remote computer to which you’re connected, and you can execute any number of PowerShell cmdlets directly on the remote system.

Enable-PSRemoting

Enable-PSRemoting configures a computer to receive PowerShell remote commands sent with WS-Management technology.

To run this cmdlet, start PowerShell with the “Run as administrator” option.

PS Remoting only needs to be enabled once on each computer that will receive commands.

Computers that only send commands do not need to have PS Remoting enabled; because the configuration activates listeners (and starts the WinRM service), it is prudent to run it only where needed.

To run a command on the remote system, use Invoke-Command or Enter-PSSession for multiple commands.

If your computers aren’t on a domain, you’ll need to perform the following extra steps:

On both computers:

Configure the TrustedHosts setting so the computers will trust each other:

Set-Item WSMan:\localhost\client\trustedhosts PC64,PC65,PC66

The comma-separated list can be IP addresses or computer names or even a * wildcard to match all.

run : Restart-Service WinRM

To view the current trusted hosts:
Get-Item WSMan:\localhost\Client\TrustedHosts

Examples

Configure the local computer to receive remote commands:

PS C:\> Enable-PSRemoting

Configure the computer to receive remote commands & suppress user prompts:

PS C:\> Enable-PSRemoting -Force

Configure the remote computer workstation64 to receive remote commands, via psexec. If you are running this from an account which is NOT a domain administrator, then specify the username/password of an account with admin rights to the remote machine:

PS C:\> psexec \\PC64 -u adminUser64 -p pa$$w0rd -h -d powershell.exe "enable-psremoting -force"

Test that the computer computer64 is setup to receive remote commands:

PS C:\> Test-WsMan PC64

Run a single command on the remote computer using Invoke-Command:

PS C:\> Invoke-Command -ComputerName PC64 -ScriptBlock { Get-ChildItem C:\ } -credential jdoe

Run multiple commands by starting a Remote PowerShell Session:

PS C:\> Enter-PSSession -ComputerName PC64 -Credential AshleyT

“He who lies hid in remote places is a law unto himself” ~ Publilius Syrus

Related PowerShell Commands:

Enter-PSSession – Start an interactive session with a remote computer.

Disable-PSRemoting – Prevent remote users from running commands on the local computer.

Test-WSMan – Test if a computer is setup to receive remote commands via the WinRM service.

Invoke-Command – Run commands on local and remote computers.

WINRM – Windows Remote Management

Question: PowerShell: Configure WinRM and enable PSRemoting

1 – Enable WinRM

First thing to do before starting to manage your server remotely is to enable this function in your server. For this, you need to use the Windows Remote Management (WinRM) service. WinRM is the service which will allow you to use the WS-Management protocol necessary for the PowerShell remoting.

Enable WinRM is quite simple to do, you just need to run this command in a PowerShell prompt:

Winrm quickconfig or winrm qc

It should display a message like this if it is already configured:

Image and video hosting by TinyPic

Otherwise it will ask you to configure it:

Image and video hosting by TinyPic

2 – Enable PSRemoting

Once you have started your WinRM service, you must configure PowerShell itself to allow the remoting:

Enable-PSRemoting

Image and video hosting by TinyPic

3 – TrustedHosts file configuration

3.1 – Add server to the TrustedHosts file

The configuration above implies a domain environment. If you are working with servers which are not in your domain or in a trusted domain, you will have to add them in the TrustedHosts list of your local server. To do so, you must run the command below:

winrm s winrm/config/client ‘@{TrustedHosts=”MyServerName”}’

And the result you should see (you just need to replace “MyServerName” by the name of your server):

Image and video hosting by TinyPic

Another way to add a server to this file, by using the Set-Item cmdlet, like below:

Set-Item WSMan:\localhost\Client\TrustedHosts –Value “MyServerName,MyServerName2”

Image and video hosting by TinyPic

In the command above you can see that I added two values between the quotes “ “. If you want to add more than one server to this file, you must add them separated by a coma. Attention anyway, if one day you decide to add a new server, if you run the same command with only one server name, it will overwrite the existing file. You need to add all the server names’ that must be in this file.

PowerShell will also prompt you to warn about the risks of adding a computer which is not trustworthy in this file.

And if I do a Get-Item, I should see my two servers:

Get-Item WSMan:\localhost\Client\TrustedHosts |fl

Image and video hosting by TinyPic

If you want to trust every servers which are not in your domain, even if it far far… far away from being secure… you can use the wildcard, like that:

Set-Item WSMan:\localhost\Client\TrustedHosts -Value “*”

Image and video hosting by TinyPic

And the result:

Get-Item WSMan:\localhost\Client\TrustedHosts |fl Name, Value

Image and video hosting by TinyPic

And of course, sometimes it can also be interesting to be able to check this TrustedHosts file to see what is inside. You can also use PowerShell to it by using the Get-Item cmdlet:

Get-Item WSMan:\localhost\Client\TrustedHosts

3.2 – Remove servers from the TrustedHosts file

While you can easily add servers to your TrustedHosts file it can also be interesting to be able to remove a server from it, for security reasons, if you don’t need to use it anymore.

To do so, there are two different ways…

Clear the whole file, by using the command below:

Clear-Item -Path WSMan:\localhost\Client\TrustedHosts –Force

Or, by only replacing one value by an empty value, with the command below:

$newvalue = ((Get-ChildItem WSMan:\localhost\Client\TrustedHosts).Value).Replace(“MyServerName1,”,””)

Set-Item WSMan:\localhost\Client\TrustedHosts $newvalue

Image and video hosting by TinyPic

And by using this command, we can remove one server but still keeping the other servers in the list. As we can see on the output below:

Image and video hosting by TinyPic

Before clearing:

Image and video hosting by TinyPic

And after:

Image and video hosting by TinyPic

And there we are! Your PowerShell is now configured to handle the remote management.

Question: PowerShell Remoting Cheatsheet

I have become a big fan of PowerShell Remoting. I find my self using it for both penetration testing and standard management tasks. In this blog I’ll share a basic PowerShell Remoting cheatsheet so you can too.

Enabling PowerShell Remoting

Before we get started let’s make sure PowerShell Remoting is all setup on your system.

  1. In a PowerShell console running as administrator enable PowerShell Remoting.Enable-PSRemoting –forceThis should be enough, but if you have to troubleshoot you can use the commands below
  2. Make sure the WinRM service is setup to start automatically.# Set start mode to automatic Set-Service WinRM -StartMode Automatic # Verify start mode and state - it should be running Get-WmiObject -Class win32_service | Where-Object {$_.name -like "WinRM"}
  3. Set all remote hosts to trusted. Note: You may want to unset this later. # Trust all hosts Set-Item WSMan:localhost\client\trustedhosts -value * # Verify trusted hosts configuration Get-Item WSMan:\localhost\Client\TrustedHosts

Executing Remote Commands with PowerShell Remoting

  • Executing a Single Command on a Remote SystemThe “Invoke-Command” command can be used to run commands on remote systems.  It can run as the current user or using alternative credentials from a non domain system.  Examples below.Invoke-Command –ComputerName MyServer1 -ScriptBlock {Hostname} Invoke-Command –ComputerName MyServer1 -Credential demo\serveradmin -ScriptBlock {Hostname} If the ActiveDirectory PowerShell module is installed it’s possible to execute commands on many systems very quickly using the pipeline. Below is a basic example.Get-ADComputer -Filter *  -properties name | select @{Name="computername";Expression={$_."name"}} | Invoke-Command -ScriptBlock {hostname} Sometimes it’s nice to run scripts stored locally on your system against remote systems.  Below are a few basic examples.Invoke-Command -ComputerName MyServer1 -FilePath C:\pentest\Invoke-Mimikatz.ps1 Invoke-Command -ComputerName MyServer1 -FilePath C:\pentest\Invoke-Mimikatz.ps1 -Credential demo\serveradmin Also, if your dynamically generating commands or functions being passed to remote systems you can use invoke-expression through invoke-command as shown below.$MyCommand = "hostname" $MyFunction = "function evil {write-host `"Getting evil...`";iex -command $MyCommand};evil" invoke-command -ComputerName MyServer1 -Credential demo\serveradmin -ScriptBlock {Invoke-Expression -Command "$args"} -ArgumentList $MyFunction
  • Establishing an Interactive PowerShell Console on a Remote SystemAn interactive PowerShell console can be obtained on a remote system using the “Enter-PsSession” command.  It feels a little like SSH.  Similar to “Invoke-Command”, “Enter-PsSession” can be run as the current user or using alternative credentials from a non domain system.  Examples below.Enter-PsSession –ComputerName server1.domain.com Enter-PsSession –ComputerName server1.domain.com –Credentials domain\serveradmin If you want out of the PowerShell session the “Exit-PsSession” command can be used.Exit-PsSession
  • Creating Background SessionsThere is another cool feature of PowerShell Remoting that allows users to create background sessions using the “New-PsSession” command.  Background sessions can come in handy if you want to execute multiple commands against many systems.  Similar to the other commands, the “New-PsSession” command can run as the current user or using alternative credentials from a non domain system.  Examples below.New-PSSession -ComputerName server1.domain.com New-PSSession –ComputerName server1.domain.com –Credentials domain\serveradmin If the ActiveDirectory PowerShell module is installed it’s possible to create background sessions for many systems at a time (However, this can be done in many ways).  Below is a command example showing how to create background sessions for all of the domain systems.  The example shows how to do this from a non domain system using alternative domain credentials.New-PSDrive -PSProvider ActiveDirectory -Name RemoteADS -Root "" -Server a.b.c.d -credential domain\user cd RemoteADS: Get-ADComputer -Filter * -Properties name  | select @{Name="ComputerName";Expression={$_."name"}} | New-PSSession
  • Listing Background SessionsOnce a few sessions have been established the “Get-PsSession” command can be used to view them.Get-PSSession
  • Interacting with Background SessionsThe first time I used this feature I felt like I was working with Metasploit sessions, but these sessions are a little more stable. Below is an example showing how to interact with an active session using the session id.Enter-PsSession –id 3 To exit the session use the “Exit-PsSession” command. This will send the session into the background again.Exit-PsSession
  • Executing Commands through Background SessionsIf your goal is to execute a command on all active sessions the “Invoke-Command” and “Get-PsSession” commands can be used together. Below is an example.Invoke-Command -Session (Get-PSSession) -ScriptBlock {Hostname}
  • Removing Background SessionsFinally, to remove all of your active sessions the “Disconnect-PsSession” command can be used as shown below.Get-PSSession | Disconnect-PSSession

Wrap Up

Naturally PowerShell Remoting offers a lot of options for both administrators and penetration testers. Regardless of your use case I think it boils down to this:

  • Use “Invoke-Command” if you’re only going to run one command against a system
  • Use “Enter-PSSession” if you want to interact with a single system
  • Use PowerShell sessions when you’re going to run multiple commands on multiple systems

Hopefully this cheatsheet will be useful. Have fun and hack responsibly.

Question: Enable PSRemoting Remotely

So it’s been an interesting week for me at work as we brought a new customer online.  It’s really great to be working with a dynamic team in a rapidly evolving environment.  One of the things that’s keeping us ahead of the game is relying on PowerShell when performing repetitive tasks.  In this week’s article I’m going to talk about a set of functions I had to come up this week to start PSRemoting remotely.

I’d seen a bunch of postings where people used Schtasks.exe and or PSExec to enable PSRemoting but I didn’t like either of those approaches.  I wanted to do it in a more native powershell way.  I got a lot of help from Thomas Lee’s blog where he talked about writing registry keys remotely using powershell.

From there I went on to write a set of functions, 5 total, that will perform all the functions required to enable PSRemoting.  In order to accomplish the configuration for the WinRM service and the windows firewall remotely I had the functions write entries in the policy node of the registry.

So I’ll stop talking and get onto the functions.

All of them can be downloaded here

Set-WinRMListener, works by creating 3 registry keys that configure the WinRM service when it restarts.

Restart-WinRM, Uses Get-WmiObject to start and stop the WinRM service.

Set-WinRMStartup, sets the startup type of the WinRM service to automatic.

Set-WinRMFirewallRule, creates 2 registry keys to configure the firewall exemptions required by PSRemoting.

Restart-WindowsFirewall, restarts the windows firewall service to allow the registry configurations to take hold.

Anyway, all the functions are defined in the script on the TechNet gallery.  I hope you guys like the functions and get some use out of them.  Go ahead and leave a comment or email me if you’re interested in further explanation.  Also, feel free to leave comments on the TechNet entry.

Question: Enable-PSRemoting

The Enable-PSRemoting cmdlet configures the computer to receive Windows PowerShell remote commands that are sent by using the WS-Management technology.

By default, on Windows Serverr 2012, Windows PowerShell remoting is enabled. You can use Enable-PSRemoting to enable Windows PowerShell remoting on other supported versions of Windows and to re-enable remoting on Windows Server 2012 if it becomes disabled.

You have to run this command only one time on each computer that will receive commands. You do not have to run it on computers that only send commands. Because the configuration starts listeners, it is prudent to run it only where it is needed.

Beginning in Windows PowerShell 3.0, the Enable-PSRemoting cmdlet can enable Windows PowerShell remoting on client versions of Windows when the computer is on a public network. For more information, see the description of the SkipNetworkProfileCheck parameter.

The Enable-PSRemoting cmdlet performs the following operations:

— Runs the Set-WSManQuickConfig cmdlet, which performs the following tasks:

—– Starts the WinRM service.

—– Sets the startup type on the WinRM service to Automatic.

—– Creates a listener to accept requests on any IP address, if one does not already exist.

—– Enables a firewall exception for WS-Management communications.

—– Registers the Microsoft.PowerShell and Microsoft.PowerShell.Workflow session configurations, if it they are not already registered.

—– Registers the Microsoft.PowerShell32 session configuration on 64-bit computers, if it is not already registered.

—– Enables all session configurations.

—– Changes the security descriptor of all session configurations to allow remote access.

—– Restarts the WinRM service to make the preceding changes effective.

To run this cmdlet, start Windows PowerShell by using the Run as administrator option.

CAUTION: On systems that have both Windows PowerShell 3.0 and Windows PowerShell 2.0, do not use Windows PowerShell 2.0 to run the Enable-PSRemoting and Disable-PSRemoting cmdlets. The commands might appear to succeed, but the remoting is not configured correctly. Remote commands and later attempts to enable and disable remoting, are likely to fail.

Examples
  1. Configure a computer to receive remote commands:PS C:> Enable-PSRemoting This command configures the computer to receive remote commands.
  2. Configure a computer to receive remote commands without a confirmation prompt:PS C:> Enable-PSRemoting -Force This command configures the computer to receive remote commands. It uses the Force parameter to suppress the user prompts.
  3. Allow remote access on clients:PS C:> Enable-PSRemoting -SkipNetworkProfileCheck -Force PS C:> Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP-PUBLIC" -RemoteAddress Any This example shows how to allow remote access from public networks on client versions of the Windows operating system. Before using these commands, analyze the security setting and verify that the computer network will be safe from harm.The first command enables remoting in Windows PowerShell. By default, this creates network rules that allow remote access from private and domain networks. The command uses the SkipNetworkProfileCheck parameter to allow remote access from public networks in the same local subnet. The command specifies the Force parameter to suppress confirmation messages.The SkipNetworkProfileCheck parameter does not affect server version of the Windows operating system, which allow remote access from public networks in the same local subnet by default.The second command eliminates the subnet restriction. The command uses the Set-NetFirewallRule cmdlet in the NetSecurity module to add a firewall rule that allows remote access from public networks from any remote location. This includes locations in different subnets.

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.