diff --git a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs index 9ba8e7186b..5af6cf39d6 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs @@ -275,6 +275,7 @@ namespace Microsoft.PowerShell.Commands public string UserName; public string KeyFilePath; public int Port; + public string Subsystem; } /// @@ -763,6 +764,13 @@ namespace Microsoft.PowerShell.Commands set; } + /// + /// This parameter specifies the SSH subsystem to use for the remote connection. + /// + [Parameter(ValueFromPipelineByPropertyName = true, + ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)] + public String Subsystem { get; set; } + #endregion #endregion Properties @@ -822,6 +830,7 @@ namespace Microsoft.PowerShell.Commands private const string KeyFilePathParameter = "KeyFilePath"; private const string IdentityFilePathAlias = "IdentityFilePath"; private const string PortParameter = "Port"; + private const string SubsystemParameter = "Subsystem"; #endregion @@ -915,6 +924,10 @@ namespace Microsoft.PowerShell.Commands { connectionInfo.Port = GetSSHConnectionIntParameter(item[paramName]); } + else if (paramName.Equals(SubsystemParameter, StringComparison.OrdinalIgnoreCase)) + { + connectionInfo.Subsystem = GetSSHConnectionStringParameter(item[paramName]); + } else { throw new PSArgumentException( @@ -1385,7 +1398,7 @@ namespace Microsoft.PowerShell.Commands { ParseSshHostName(computerName, out string host, out string userName, out int port); - var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port); + var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port, this.Subsystem); var typeTable = TypeTable.LoadDefaultTypeFiles(); var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace; var pipeline = CreatePipeline(remoteRunspace); @@ -1407,7 +1420,8 @@ namespace Microsoft.PowerShell.Commands sshConnection.UserName, sshConnection.ComputerName, sshConnection.KeyFilePath, - sshConnection.Port); + sshConnection.Port, + sshConnection.Subsystem); var typeTable = TypeTable.LoadDefaultTypeFiles(); var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace; var pipeline = CreatePipeline(remoteRunspace); diff --git a/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs b/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs index 6e26b815ec..1501bd974d 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs @@ -1282,7 +1282,7 @@ namespace Microsoft.PowerShell.Commands private RemoteRunspace GetRunspaceForSSHSession() { ParseSshHostName(HostName, out string host, out string userName, out int port); - var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port); + var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port, this.Subsystem); var typeTable = TypeTable.LoadDefaultTypeFiles(); // Use the class _tempRunspace field while the runspace is being opened so that StopProcessing can be handled at that time. diff --git a/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs b/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs index f5840c7ea9..217148ae71 100644 --- a/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs @@ -1080,7 +1080,8 @@ namespace Microsoft.PowerShell.Commands userName, host, this.KeyFilePath, - port); + port, + Subsystem); var typeTable = TypeTable.LoadDefaultTypeFiles(); string rsName = GetRunspaceName(index, out int rsIdUnused); index++; @@ -1105,7 +1106,8 @@ namespace Microsoft.PowerShell.Commands sshConnection.UserName, sshConnection.ComputerName, sshConnection.KeyFilePath, - sshConnection.Port); + sshConnection.Port, + sshConnection.Subsystem); var typeTable = TypeTable.LoadDefaultTypeFiles(); string rsName = GetRunspaceName(index, out int rsIdUnused); index++; diff --git a/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs b/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs index f9580a9db4..2b362f1c52 100644 --- a/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs +++ b/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs @@ -1867,6 +1867,15 @@ namespace System.Management.Automation.Runspaces set; } + /// + /// Subsystem to use + /// + private string Subsystem + { + get; + set; + } + #endregion #region Constructors @@ -1894,6 +1903,7 @@ namespace System.Management.Automation.Runspaces this.ComputerName = computerName; this.KeyFilePath = keyFilePath; this.Port = DefaultPort; + this.Subsystem = DefaultSubsystem; } /// @@ -1903,15 +1913,18 @@ namespace System.Management.Automation.Runspaces /// Computer Name /// Key File Path /// Port number for connection (default 22) + /// Subsystem to use (default 'powershell') public SSHConnectionInfo( string userName, string computerName, string keyFilePath, - int port) : this(userName, computerName, keyFilePath) + int port, + string subsystem) : this(userName, computerName, keyFilePath) { ValidatePortInRange(port); this.Port = (port != 0) ? port : DefaultPort; + this.Subsystem = (String.IsNullOrEmpty(subsystem)) ? DefaultSubsystem : subsystem; } #endregion @@ -1965,6 +1978,7 @@ namespace System.Management.Automation.Runspaces newCopy.UserName = this.UserName; newCopy.KeyFilePath = this.KeyFilePath; newCopy.Port = this.Port; + newCopy.Subsystem = this.Subsystem; return newCopy; } @@ -2040,14 +2054,14 @@ namespace System.Management.Automation.Runspaces } arguments = (string.IsNullOrEmpty(domainName)) ? - string.Format(CultureInfo.InvariantCulture, @"-i ""{0}"" {1}@{2} -p {3} -s powershell", this.KeyFilePath, userName, this.ComputerName, this.Port) : - string.Format(CultureInfo.InvariantCulture, @"-i ""{0}"" -l {1}@{2} {3} -p {4} -s powershell", this.KeyFilePath, userName, domainName, this.ComputerName, this.Port); + string.Format(CultureInfo.InvariantCulture, @"-i ""{0}"" {1}@{2} -p {3} -s {4}", this.KeyFilePath, userName, this.ComputerName, this.Port, this.Subsystem) : + string.Format(CultureInfo.InvariantCulture, @"-i ""{0}"" -l {1}@{2} {3} -p {4} -s {5}", this.KeyFilePath, userName, domainName, this.ComputerName, this.Port, this.Subsystem); } else { arguments = (string.IsNullOrEmpty(domainName)) ? - string.Format(CultureInfo.InvariantCulture, @"{0}@{1} -p {2} -s powershell", userName, this.ComputerName, this.Port) : - string.Format(CultureInfo.InvariantCulture, @"-l {0}@{1} {2} -p {3} -s powershell", userName, domainName, this.ComputerName, this.Port); + string.Format(CultureInfo.InvariantCulture, @"{0}@{1} -p {2} -s {3}", userName, this.ComputerName, this.Port, this.Subsystem) : + string.Format(CultureInfo.InvariantCulture, @"-l {0}@{1} {2} -p {3} -s {4}", userName, domainName, this.ComputerName, this.Port, this.Subsystem); } System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo( @@ -2082,6 +2096,11 @@ namespace System.Management.Automation.Runspaces /// private const int DefaultPort = 22; + /// + /// Default value for subsystem + /// + private const string DefaultSubsystem = "powershell"; + #endregion #region SSH Process Creation