Coffee Break – Windows PowerShell Remoting

In this previous blog post we looked briefly at Windows PowerShell and remoting. Back then, we used a PSSession object to connect to a Microsoft Dynamics NAV virtual machine in Microsoft Azure. This time we will look a little closer at just the PSSession object.

Coffee Break 8 – Windows PowerShell Remoting (On-Premises)

Taking a closer look at ways to run PowerShell on remote machines on your network.

But first, if you think you need more study to start with this, then please check out this free Professional Education online course, offered by Microsoft and EdX:
Windows PowerShell Fundamentals

Customer Story:

The customer’s IT administrator want to remotely check Microsoft Dynamics NAV Server instances on their network. And they want to be able to script tasks and run those scripts from their laptop. So connecting to each (NAV) server with RDC is not an option. In fact now we are at it, why not remote from your mobile phone?

Basic installation guide for Windows PowerShell Web Access

How to do PowerShell on your phone

Customer Story II (The Sequel):

A problem of some kind has occurred on one of the installations and services need to get restarted/updated/tenants mounted. The customer’s IT administrator is in a traffic jam. A long phone call with instructions on what to press or not is one option. But PowerShell web access from the mobile, and simple web-run remote management while still stuck in that traffic jam might be a better one. More about this to come soon!

Challenge:

Next time you need to restart a NAV Server, change a config value or do any other (NAV) admin task that you can do with PowerShell, try to do it without actually connecting (RDC) to the machine. Do it via a PowerShell prompt on your machine.

 

PowerShell Remoting:

Imagine that you are sitting with your laptop, and from there you need to access (NAV) services on various different machines on your domain.

Option 1: -Computername
Many cmdlets implement the -Computername parameter, for example:

$RemoteServer = “MyServerName
Get-ServiceComputerName $RemoteServer # shows you Windows services on [MyServerName]

This is the simplest way to run a cmdlet remotely. But there is no general rule that every cmdlet must implement the -ComputerName parameter or if they do, then how.

 

Option 2: Invoke-Command
Invoke-Command is a cmdlet that will send whatever command to the remote machine. Example:
  Invoke-CommandComputerName $RemoteServerScriptBlock{get-service}
or run anything that you are used to run from a cmd prompt
  Invoke-CommandComputerName $RemoteServerScriptBlock{ipconfig}
or

  Invoke-CommandComputerName $RemoteServerScriptBlock{dir C:\}
or even (though a bit pointless)
  Invoke-CommandComputerName $RemoteServerScriptBlock{calc}

If you want to prompt for credentials on the remote machine:

  Invoke-Command {Get-Service} –computername $RemoteServerCredential Get-Credential

Invoke-Command creates a new session, so to run a NAV cmdlet we first need to import the NAV management module and then run our NAV cmdlet. Each command separated by semi-colon:
  Invoke-CommandComputerName $RemoteServer `
   –ScriptBlock {Import-Module ‘C:\Program Files\Microsoft Dynamics NAV\80\Service\Microsoft.Dynamics.Nav.Management.dll’ `
   ; Get-NAVServerInstance | Format-TableAutoSize}

 Note that in this example you do not need to have NAV on the machine you are running from. The only cmdlet that runs on your machine is Invoke-Command.

You can also run a script remotely. If you first create a script like this:

  Import-Module ‘C:\Program Files\Microsoft Dynamics NAV\80\Service\Microsoft.Dynamics.Nav.Management.dll’
  Get-NAVServerInstance | Format-TableAutoSize

Save it as c:\Tech\GetNAVServers.ps1

Then run it:

  Invoke-CommandComputerName $RemoteServerFilePath{C:\Tech\GetNAVServers.ps1}

Notice that the script is saved locally on your machine, but it runs on the remote machine.

We can add parameters to this script by adding –ArgumentList Arg1, Arg2, Argn. Let’s make a small addition to the script by adding a Microsoft Dynamics NAV Server instance name as a parameter:

  Param($NAVInstanceName)
  Import-Module ‘C:\Program Files\Microsoft Dynamics NAV\80\Service\Microsoft.Dynamics.Nav.Management.dll’
  Get-NAVServerInstance $NAVInstanceName | Format-TableAutoSize

(if you want more than one parameter, just comma-separate them like this Param($NAVInstanceName, $Tenant, $UserName, … etc)

Try to just run the script (locally):

  CD C:\Tech\

  .\GetNAVServers.ps1NAVInstanceName DynamicsNAV80

And remotely:

  Invoke-CommandComputerName $RemoteServerFilePath{C:\Tech\GetNAVServers.ps1} –ArgumentList Dynamicsnav80

 

Option 3: PSSession
As mentioned before, Invoke-Command will create a new session. But we can also create a new session separately, and then re-use this session. Why?

  •   It takes time to open a session, so we can potentially save some time by re-using one session.
  •   The session is persistent (keeps variable values), which could also be of use.

Creating a remote session of course requires authentication. As long as we are remoting to a machine on our domain then Windows will take care of this. Creating a remote session to a machine in the cloud requires certificate. For this, see the previous blog (linked in the top of this one). But here we just want to open session(s) on our own network. But notice that once you have your PSSession object, then the rest of the syntax is exactly the same, whether the session is to a machine under your desk, or to a machine in an Azure data centre. Create a session to a machine ($RemoteServer) on your network could not be easier:

  $MySession = New-PSSession $RemoteServer

Now you can (re) use this session with Invoke-Command. So in the examples above, just use -Session parameter instead of -ComputerName:
  Invoke-CommandSession $MySessionScriptBlock{get-service}

The next example will show what it means that the session is persistent:
  Invoke-CommandSession $MySessionScriptBlock{$i++;$i}

Run that one a few times, and see that $i increments every time.

Or you can enter a remote manual session:

  Enter-pssession $MySession

Notice that the first part of the prompt changes to show you that the prompt is now running on the remote machine. To leave this machine and return PowerShell to your local machine, run EXIT.

Troubleshooting:

On some (client) OS, PowerShell remoting is not enabled by default. PowerShell remoting runs under a service called WinRM. To test it:

Test-connectionComputerName $RemoteServer
Test-wsmanComputerName $RemoteServer

And as also mentioned by Pallea in comments to the blog linked above (thanks!), if remoting is not enabled you can enable it in this way:

Enable-PSRemoting

 

 

Jasminka Thunes, Escalation Engineer Dynamics NAV EMEA

Lars Lohndorf-Larsen, Escalation Engineer Dynamics NAV EMEA

Bas Graaf, Senior Software Engineer Dynamics NAV