This self-answered question, which focuses on Windows[1], addresses the following aspects:
Now that there are two PowerShell editions - the legacy, Windows-only Windows PowerShell and the cross-platform PowerShell (Core) 7, both may be installed on a given Windows machine:
How can I tell which PowerShell edition will execute remote commands, such as via Invoke-Command -ComputerName
?
How can I target a specific edition, both ad hoc and persistently, through configuration?
Note:
For an edition to be targetable via remoting on a given machine, it must be set up for remoting:
Only Windows PowerShell is automatically set up for remoting, but only on servers running Windows Server 2012 or higher.
As of v7.x, PowerShell Core doesn't come with Windows (yet?); if you're using the official installer, you're given the option of enabling remoting during the installation.
In any event, you can use Enable-PSRemoting
to (re-)enable PowerShell remoting on demand, which:
must be run from the respective edition.
must be run with administrative privileges
[1] That is, the question focuses on WinRM-based remoting (WinRM is a Windows-specific implementation of the DTMF WSMan (WS-Management) standard).
As for cross-platform remoting with PowerShell (Core) 7:
You can already use SSH-based remoting, on all platforms:
Using SSH-based remoting involves mostly the same cmdlets as WinRM-based remoting, though the parameters involved differ; most notably, you specify the target computer(s) via the -HostName
parameter rather than
the -ComputerName
parameter.
Limitations (as of v7.x): "SSH-based remoting doesn't currently support remote endpoint configuration and Just Enough Administration (JEA)."
For Unix-to-Windows remoting (Unix referring to Unix-like platforms such as macOS and Linux) - that is, remoting into a Windows machine from a Unix-like machine - you can alternatively use WinRM-based remoting with additional configuration:
The Unix-like machines must use the remoting cmdlets with the -Authentication Basic -UseSsl
parameters.
[Repository is now archived] A Unix WSMan-based implementation is being worked on in the psl-omi-provider repository, which already enables Linux machines to act as remoting targets (that is, the server component is already usable - it's not clear to me whether it can also be installed on macOS); the client component, however, is not yet production-ready as of this writing.
Once the client client component is available, uniform WSMan-based cross-platform remoting will be possible, both between Unix-like machines (Linux, macOS) and between Unix-like machines and Windows machines.
Note: Changing what remote endpoint PowerShell [Core] targets by default - which as of 7.0 is still Window PowerShell - is being considered: see GitHub issue #11616.
It is the locally specified remoting session configuration that determines what PowerShell edition, and possibly version, will be used on the remote machine:
Ad hoc, you can use the -ConfigurationName
parameter of remoting cmdlets such as Invoke-Command
, New-PSSession
, and Enter-PSSession
to specify a session configuration explicitly.
Persistently, via configuration, you can set the default session configuration via the $PSSessionConfigurationName
preference variable (the linked help topic also dicusses other remote-session-related preference variables, namely $PSSessionApplicationName
and $PSSessionOption
)
microsoft.powershell
on the remote machine (see below). Therefore, you can alternatively change the definition of this configuration on the remote target machine, but note that this means that all clients that use the defaults will use the redefined configuration - see bottom for how to achieve this redefinition.On the target machine of a remoting operation, Get-PSSessionConfiguration
cmdlet lists all registered session configurations that clients can use to connect to, and which you can manage with Register-PSSessionConfiguration
and Unregister-PSSessionConfiguration
:
Caveat: Get-PSSessionConfiguration
must be run in an elevated session (as administrator), and, due to a bug in Windows PowerShell 5.1, you may have to run the following dummy command first: $null = Get-Command Test-WSMan
, so as to ensure that the wsman:
drive is defined).
Session configurations whose names are prefixed with 'microsoft.powershell
' belong to Windows PowerShell.
Prefix 'PowerShell.'
refers to PowerShell Core.
$PSSessionConfigurationName
defaults to 'http://schemas.microsoft.com/powershell/Microsoft.PowerShell'
in both editions, which means that Windows PowerShell is by default targeted on remote machines even if you're running from PowerShell Core:
The Microsoft.PowerShell
part refers to the (64-bit) Windows PowerShell session configuration, as listed by Get-PSSessionConfiguration
(in lowercase).
The http://schemas.microsoft.com/powershell/
prefix is optional and can be omitted; note that using https:
in the prefix does not work and will not automatically switch to an SSL-based transport; for the latter, explicit configuration is needed. Note that HTTPS/SSL-based remoting isn't necessary if all of your remoting happens within a Windows domain.
To target PowerShell (Core) 7 on a remote machine:
Generally, PowerShell (Core) session configurations are version-specific, and you have two choices:
Target a major PowerShell (Core) version - e.g., PowerShell.7
- using whatever the latest v7.x version is installed on the target machine.
Target a specific version - e.g., PowerShell.7.1.2
Again, running Get-PSSessionConfiguration
on the target machine, from an elevated session, tells you the names of all registered session configurations.
To target PowerShell 7 ad hoc, use -ConfigurationName PowerShell.7
, for instance:
# Connect to computer $comp and make it execute $PSVersionTable
# in PowerShell Core v7.x, which tells you what PowerShell edition
# and version is running.
Invoke-Command -ComputerName $comp -ConfigurationName PowerShell.7 { $PSVersionTable }
$PROFILE
file:# When remoting, default to running PowerShell (Core) v7.x on the
# the target machines:
$PSSessionConfigurationName = 'PowerShell.7'
microsoft.powershell
session configuration, which requires administrative privileges; you can adapt the following snippet:# Run WITH ELEVATION (as administrator) and
# ONLY IF YOU UNDERSTAND THE IMPLICATIONS.
$ErrorActionPreference = 'Stop'
# The configuration whose definition you want to make the new default.
$newDefaultConfigSource = 'PowerShell.7'
# Standard registry locations and names.
$defaultConfigName = 'Microsoft.PowerShell'
$configXmlValueName = 'ConfigXml'
$configRootKey = 'registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Plugin'
# Rename the current default configuration XML to "ConfigXml.OLD" to keep a backup.
Rename-ItemProperty $configRootKey\$defaultConfigName $configXmlValueName -NewName "$configXmlValueName.OLD"
# Get the configuration XML from the configuration that should become the new default.
# Modify it to replace the source configuration name with the default configuration name.
$xmlText = (Get-ItemPropertyValue $configRootKey\$newDefaultConfigSource $configXmlValueName) -replace
('\b{0}\b' -f [regex]::Escape($newDefaultConfigSource)), $defaultConfigName
# Save the modified XML as the default configuration's config XML.
Set-ItemProperty $configRootKey\$defaultConfigName $configXmlValueName $xmlText
# Restart the WinRM service for changes to take effect.
Restart-Service WinRM