This document briefly describes remoting commandlets, requirements, help notices and design used in this repository.
A brief breakdown that is of interest, according to Microsoft docs.
Windows Remote Management
firewall rules to PersistentStore (required by WinRM)Set-WSManQuickConfig -UseSSL
will not work if your certificate is self signed
Set-WSManQuickConfig
Deny_All
Network_Deny_All
1
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\LocalAccountTokenFilterPolicy
This provides remote access to session configurations that were reserved for local use.
LocalAccountTokenFilterPolicy = 1
allows remote access to members of the Administrators group.
Deny_All
setting from the security descriptorWSMan:\<computer>\PlugIn\<SessionConfigurationName>\Enabled
to True.Does not remove or change the Network_Deny_All
Changes the security descriptor of all session configurations to block remote access
Network_Deny_All
Will not undo the following:
Windows Remote Management
firewall rules (including compatibility rules)Deny_All
if it was present previously0
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\LocalAccountTokenFilterPolicy
LocalAccountTokenFilterPolicy = 0
blocks remote access to members of the Administrators group.
Because Deny_All
was not added, loopback connections are still allowed, for requirements see
WinRM on loopback
Deny_All
setting to the security descriptorWSMan:\<computer>\PlugIn\<SessionConfigurationName>\Enabled
to False.A loopback connection is created when the following conditions are met:
localhost
-EnableNetworkAccess
switch parameter is used with New-PSSession
For loopback remoting reference see Disable-PSRemoting
Deny_All
block all users from using session configuration, both remote and localNetwork_Deny_All
allow only users of the local computer to use the session configuration,
either loopback or trough network stackFor details see -AccessMode
parameter description here AccessMode
To add or remove these flags to configurations manually use Set-PSSessionConfiguration
-SkipNetworkProfileCheck
switch parameter is available only by the following commandlets:
Set-WSManQuickConfig
Enable-PSRemoting
Enable-PSSessionConfiguration
If you have Hyper-V installed that means some virtual switches will operate on public network even if you’re on private network profile, which means you won’t be able to configure all possible WinRM service options, except only with those commandlets listed above.
Disabling those virtual switches is required in that case, uninstalling Hyper-V is an alternative solution if disabling does not work.
Of course any remaining network adapters must operate on private network profile.
For reference see -SkipNetworkProfileCheck
parameter description.
In this repository for PowerShell [Microsoft.Win32.RegistryKey]
class is used for remote registry.
For reference see RegistryKey
The following requirements apply to both endpoints involved (client and server computers):
RemoteRegistry
service is set to Manual (Trigger Start)
startup on both endpointsFile and Printer sharing
Network Discovery
Private
or Domain
network profile on both endpoints.To initiate remote registry connection you must authenticate to remote computer with username and
password of the user account on remote computer that belongs to Administrators
group.
[Microsoft.Win32.RegistryKey]
does not provide any authentication methods, therefore to use it in
PowerShell the solution is to open network drive as follows:
$RemoteComputer = "COMPUTERNAME"
$RemotingCredential = Get-Credential
New-PSDrive -Credential $RemotingCredential -PSProvider FileSystem -Name RemoteRegistry `
-Root \\$RemoteComputer\C$ -Description "Remote registry authentication" | Out-Null
Note that Registry provider -PSProvider Registry
does not support specifying credentials but
specifying FileSystem
does the trick.
If New-PSDrive
fails with “The network path was not found” try restarting fdphost
service on
both computers or reboot both computers.
Alternatively, creating a new remote share and authenticating to it instead of default C$
can help.
Methods of the [Microsoft.Win32.RegistryKey]
class may throw various exceptions but not all are
handled in this repository except for initial registry authentication and root key access to avoid
code bloat.
At a minimum you should handle OpenRemoteBaseKey
and opening root key (but not subsequent subkeys)
with OpenSubkey
exceptions.
The following is an example which you can copy\paste to problem script to get detailed problem description.
try
{
Write-Verbose -Message "[$($MyInvocation.InvocationName)] Accessing registry on computer: $RemoteComputer"
$RemoteKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegistryHive, $RemoteComputer, $RegistryView)
}
catch [System.UnauthorizedAccessException]
{
Write-Error -Category AuthenticationError -TargetObject $RegistryHive -Message $_.Exception.Message
Write-Warning -Message "[$($MyInvocation.InvocationName)] Remote registry access was denied for $([Environment]::MachineName)\$([Environment]::UserName) by $RemoteComputer system"
return
}
catch [System.Security.SecurityException]
{
Write-Error -Category SecurityError -TargetObject $RegistryHive -Message $_.Exception.Message
Write-Warning -Message "[$($MyInvocation.InvocationName)] $($RemotingCredential.UserName) does not have the requested ACL permissions for $RegistryHive hive"
return
}
catch
{
Write-Error -ErrorRecord $_
return
}
try
{
Write-Verbose -Message "[$($MyInvocation.InvocationName)] Opening root key: HKLM:\$HKLM"
$RootKey = $RemoteKey.OpenSubkey($HKLM, $RegistryPermission, $RegistryRights)
if (!$RootKey)
{
throw [System.Data.ObjectNotFoundException]::new("The following registry key does not exist: HKLM:\$HKLM")
}
}
catch [System.Security.SecurityException]
{
Write-Error -Category SecurityError -TargetObject $HKLM -Message $_.Exception.Message
Write-Warning -Message "[$($MyInvocation.InvocationName)] $($RemotingCredential.UserName) does not have the requested ACL permissions for $HKLM key"
}
catch
{
Write-Error -ErrorRecord $_
}
finally
{
if ($RemoteKey)
{
$RemoteKey.Dispose()
}
Write-Error -ErrorRecord $_
return
}
For additional breakdown of registry key naming convention and exceptions see NamingConvention.md
The following link lists common issues with remoting and how to troubleshoot them About Remote Troubleshooting
The following section lists other not so common problems and how to resolve them.
TODO: missing resolutions for the following known problems:
Connecting to remote server COMPUTERNAME failed with the following error message : The WinRM client sent a request to an HTTP server and got a response saying the requested HTTP URL was not available. This is usually returned by a HTTP server that does not support the WS-Management protocol.
When you specify computername, it is translated to private IP address for which listener must exist.
WinRM service is not listening on the translated IP address, to add listener for any IP address run:
New-Item -Path WSMan:\localhost\Listener -Address * -Transport HTTP -Enabled $true -Force | Out-Null
or alternatively:
New-WSManInstance -ResourceURI winrm/config/Listener -ValueSet @{ Enabled = $true } `
-SelectorSet @{ Address = "*"; Transport = "HTTP" } | Out-Null
Set-Item -Path WSMan:\localhost\Client\Auth\Negotiate -Value $true
Restart-Service -Name WinRM
If not working then:
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Client\ `
-Name auth_negotiate -Value ([int32] ($AuthenticationOptions["Negotiate"] -eq $true))
Restart-Service -Name WinRM
The server certificate on the destination computer (localhost) has the following errors: Encountered an internal error in the SSL library.
If using SSL on localhost, it would go trough network stack and for this you need authentication, which means specifying host name, user name and password.
Access is denied
If credentials are required, this may happen due to invalid username\password.
It may also happen if the administrative account used to deploy firewall has no password set,
in which case password must be set because WinRM doesn’t support passwordless authentication.
Although it should be possible for passwordless logon by configuring GPO on remote computer:
Computer Configuration/Windows Settings/Security Settings/Local Policies/Security Options/Accounts:
Limit local account use of blank passwords to console logon only
[localhost] Connecting to remote server localhost failed with the following error message: Access is denied.
If this happens in Initialize-WinSession
it’s because session configuration was disabled in
Windows PowerShell, ex. by using Reset-Firewall -Remoting
, to fix this problem run in Windows PowerShell:
Set-PSSessionConfiguration -Name Microsoft.PowerShell -AccessMode Remote
Otherwise check the following 3 things:
Verify PS session configuration which is being used is enabled
Get-PSSessionConfiguration -Name "NameOfTheSession" | Enable-PSSessionConfiguration
NOTE: To get Windows PowerShell session configurations use Get-PSSessionConfiguration
in
Windows PowerShell
Verify access mode of the session PS configuration is set to Remote
Set-PSSessionConfiguration -Name "NameOfTheSession" -AccessMode Remote
Verify LocalAccountTokenFilterPolicy
is enabled (set to 1)
Set-ItemProperty -Name LocalAccountTokenFilterPolicy -Value 1 `
-Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
Verify access permissions for user or group on remote host per session in question
Set-PSSessionConfiguration -ShowSecurityDescriptorUI -Name NameOfTheSession
The following sections list CIM related errors and how to resolve them
Error description example:
Get-CimInstance: The WS-Management service does not support the specified polymorphism mode. Try changing the polymorphism mode specified, and try again.
Error resolution:
The Web Services Management Protocol Extensions for Windows Vista service MUST return instances of both base and derived classes. Each returned instance MUST contain the properties of the base class. Each returned instance MAY omit the properties from the derived classes and MAY set the instance type of derived classes to the base class.
Hint: do not use -Shallow
parameter with Get-CimInstance
commandlet
The WS-Management service cannot process the request. The service is configured to reject remote connection requests for this plugin
You get this error when running Get-CimInstance -CimSession $CimServer
where $CimServer
is
your already established remote CIM session.
First step is to harvest plugin status as follows:
Get-Item WSMan:\localhost\Plugin\* | ForEach-Object {
$Enabled = Get-Item "WSMan:\localhost\Plugin\$($_.Name)\Enabled" |
Select-Object -ExpandProperty Value
[PSCustomObject] @{
Name = $_.Name
Enabled = $Enabled
PSPath = $_.PSPath
}
} | Sort-Object -Property Enabled -Descending | Format-Table -AutoSize
Sample output may look like this:
Name Enabled PSPath
---- ------- ------
RemoteFirewall True Microsoft.WSMan.Management\WSMan::localhost\Plugin\RemoteFirewall
Microsoft.PowerShell True Microsoft.WSMan.Management\WSMan::localhost\Plugin\Microsoft.PowerShell
WMI Provider False Microsoft.WSMan.Management\WSMan::localhost\Plugin\WMI Provider
Microsoft.PowerShell32 False Microsoft.WSMan.Management\WSMan::localhost\Plugin\Microsoft.PowerShell32
Event Forwarding Plugin False Microsoft.WSMan.Management\WSMan::localhost\Plugin\Event Forwarding Plugin
Microsoft.Powershell.Workflow False Microsoft.WSMan.Management\WSMan::localhost\Plugin\Microsoft.Powershell.Workflow
As you can see WMI Provider
plugin is not enabled in this example which does the following:
WMI allows you to manage local and remote computers and models computer and network objects using an extension of the Common Information Model (CIM) standard
Since this plugin is required to run CIM commands against remote computer you enable it like this:
Set-Item -Path WSMan:\localhost\Plugin\"WMI Provider"\Enabled -Value $true
Restart-Service -Name WinRM
For more information see WMI plug-in configuration notes
Most likely you need to specify credentials
See the following link Troubleshooting Remote Registry
The following section lists module functions and scripts which support or do not support remoting by design, as well as functions which currently lack remoting implementation or are unfinished for remoting.
The following modules do no expose any remoting functionality at all by design
The following modules lack remoting functionality
The following functions support remoting but were not tested for remoting
The following functions do not implement remoting and it’s unclear if it’s needed
The following functions support remoting
The following functions lack remoting implementation
All other public functions do not support remoting by design
The following functions support remoting
The following functions do not support remoting by design
All other public functions lack remoting implementation
The following functions do not support remoting by design
The following functions support remoting with PowerShell Core only
All other public functions support remoting
The following functions support remoting
All other functions do not implement remoting and it’s unclear if remoting is needed
The following functions do not support remoting by design
The following functions lack remoting implementation
The following functions support remoting but may fail
All other functions support remoting
The following functions support remoting
The following functions lack remoting implementation
All other functions do not support remoting by design
The following scripts support remoting
The following scripts lack remoting implementation
All other scripts do not support remoting by design