I am not sure if this is the best place to ask this question. Please let me know if there is a better place to ask this question. I already have asked this question on stack overflow with no response yet.
I am attempting to write a C# core program using the powershell core SDK to run powershell scripts on remote Linux systems. Running on .net core is a requirement for this project. I am trying to loosely follow a guide I found on CodeProject.
This is my code:
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
SSHConnectionInfo connectionInfo = new SSHConnectionInfo(userName: "user", computerName: "server", keyFilePath: "id_rsa");
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
runspace.Open(); // The program errors out here
runspace.Close();
}
}
}
}
This is the error I am receiving:
Unhandled Exception: System.Management.Automation.Remoting.PSRemotingDataStructureException: An error has occurred which PowerShell cannot handle. A remote session might have ended. ---> System.ArgumentException: The path is not of a legal form.
Parameter name: path
at System.IO.Path.GetDirectoryName(String path)
at System.Management.Automation.Runspaces.SSHConnectionInfo.StartSSHProcess(StreamWriter& stdInWriterVar, StreamReader& stdOutReaderVar, StreamReader& stdErrReaderVar)
at System.Management.Automation.Remoting.Client.SSHClientSessionTransportManager.CreateAsync()
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerImpl.SendNegotiationAsync(RemoteSessionState sessionState)
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerImpl.HandleStateChanged(Object sender, RemoteSessionStateEventArgs arg)
at System.Management.Automation.ExtensionMethods.SafeInvoke[T](EventHandler`1 eventHandler, Object sender, T eventArgs)
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerStateMachine.RaiseStateMachineEvents()
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerStateMachine.ProcessEvents()
--- End of inner exception stack trace ---
at System.Management.Automation.Runspaces.AsyncResult.EndInvoke()
at System.Management.Automation.Runspaces.Internal.RunspacePoolInternal.EndOpen(IAsyncResult asyncResult)
at System.Management.Automation.Runspaces.Internal.RemoteRunspacePoolInternal.Open()
at System.Management.Automation.RemoteRunspace.Open()
at ConsoleApp1.Program.Main(String[] args) in C:\ConsoleApp1\ConsoleApp1\Program.cs:line 18
Press any key to continue . . .
It appears that my C# program is unable to find the openssh executable.
Installed Software:
At this point I am not sure what I am missing.
I apologize, I forgot to mention that I am able to use PowerShell 6.0.2 on the same Windows PC to remote into Linux servers using SSH without issue. I will continue to look through the documentation. If you have any other suggestions I welcome them.
Using a pre-release version of powershell core 6.1 and facing a similar issue. Is there some documentation which I can refer to regarding ssh-ing into Linux using C# and powershell. I can use powershell to start a new-pssession and a ssh key file path with host and user names. But when I try to invoke the same script using the Powershell Core SDK dlls, I am having an issue.
@PaulHigin Could you please comment the Issue?
@arahja
It looks like you are not passing in a full path to the rsa key file path parameter:
SSHConnectionInfo connectionInfo = new SSHConnectionInfo(userName: "user", computerName: "server", keyFilePath: "/Users/user/MyKeys/id_rsa");
But if you have the id_rsa key file in the user path expected by SSH, you don't need to pass in the key file path and SSH will find it. This works for me.
SSHConnectionInfo connectionInfo = new SSHConnectionInfo(userName: "user", computerName: "localMachine", keyFilePath: null);
Note that you can experiment with this using PowerShell APIs on the command line:
$ci = [System.Management.Automation.Runspaces.SSHConnectionInfo]::new("user","localMachine",$null)
$rs = [runspacefactory]::CreateRunspace($ci)
$rs.Open()
$rs
Id Name ComputerName Type State Availability
-- ---- ------------ ---- ----- ------------
3 Runspace3 localMachine Local Opened Available
Actually, looking at this closer it does seem that this error is about finding the ssh command. The code uses PowerShell's command discovery to look up the filepath. It uses environment variables to find the ssh command and if it is failing it may be because your hosting process does not have the correct environment set up. Also you should be able to get the command from a PowerShell command line:
CommandType Name Version Source
----------- ---- ------- ------
Application ssh 0.0.0.0 /usr/bin/ssh
Currently this .net core program is running on Windows. I do have "C:Program FilesOpenSSH" in my Path environment variable. On the same system Powershell Core is able to use OpenSSH.
I did retry with the full path to the id_rsa file and I recieved this error:
{System.Management.Automation.Remoting.PSRemotingDataStructureException: An error has occurred which PowerShell cannot handle. A remote session might have ended. ---> System.InvalidOperationException: Failed to start the SSH client process needed for the remoting connection with error: The filename, directory name, or volume label syntax is incorrect. ---> System.ComponentModel.Win32Exception: The filename, directory name, or volume label syntax is incorrect
at System.Management.Automation.Runspaces.SSHConnectionInfo.CreateProcessWithRedirectedStd(ProcessStartInfo startInfo, SafePipeHandle& stdInPipeServer, SafePipeHandle& stdOutPipeServer, SafePipeHandle& stdErrPipeServer)
at System.Management.Automation.Runspaces.SSHConnectionInfo.StartSSHProcessImpl(ProcessStartInfo startInfo, StreamWriter& stdInWriterVar, StreamReader& stdOutReaderVar, StreamReader& stdErrReaderVar)
--- End of inner exception stack trace ---
at System.Management.Automation.Runspaces.SSHConnectionInfo.StartSSHProcessImpl(ProcessStartInfo startInfo, StreamWriter& stdInWriterVar, StreamReader& stdOutReaderVar, StreamReader& stdErrReaderVar)
at System.Management.Automation.Runspaces.SSHConnectionInfo.StartSSHProcess(StreamWriter& stdInWriterVar, StreamReader& stdOutReaderVar, StreamReader& stdErrReaderVar)
at System.Management.Automation.Remoting.Client.SSHClientSessionTransportManager.CreateAsync()
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerImpl.SendNegotiationAsync(RemoteSessionState sessionState)
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerImpl.HandleStateChanged(Object sender, RemoteSessionStateEventArgs arg)
at System.Management.Automation.ExtensionMethods.SafeInvoke[T](EventHandler``1 eventHandler, Object sender, T eventArgs)
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerStateMachine.RaiseStateMachineEvents()
at System.Management.Automation.Remoting.ClientRemoteSessionDSHandlerStateMachine.ProcessEvents()
--- End of inner exception stack trace ---
at System.Management.Automation.Runspaces.AsyncResult.EndInvoke()
at System.Management.Automation.Runspaces.Internal.RunspacePoolInternal.EndOpen(IAsyncResult asyncResult)
at System.Management.Automation.Runspaces.Internal.RemoteRunspacePoolInternal.Open()
at System.Management.Automation.RemoteRunspace.Open()
at remote_powershell.Program.Main(String[] args) in C:\Users\arahja\Documents\Visual Studio 2017\Projects\ConsoleApp1\ConsoleApp1\Program.cs:line 17} System.Management.Automation.Remoting.PSRemotingDataStructureException
Yes, this error indicates that PowerShell is not finding the file path to ssh.exe ("The filename, directory name, or volume label syntax is incorrect"). But I think I know what the problem is. The code uses PowerShell command look up to get the file path for ssh.exe, and for this it uses the default runspace.
var cmdInfo = context.CommandDiscovery.LookupCommandInfo(sshCommand, CommandOrigin.Internal) as ApplicationInfo;
But since you are hosting SMA.dll directly and probably have not executed any locally running PowerShell scripts, there is no default runspace. Try adding this to your code:
if (System.Management.Automation.Runspaces.Runspace.DefaultRunspace == null)
{
var defaultRunspace = RunspaceFactory.CreateRunspace();
defaultRunspace.Open();
System.Management.Automation.Runspaces.Runspace.DefaultRunspace = defaultRunspace;
}
Actually I think this is a bug in PowerShell, and it should create a runspace to find the command if needed, or at the very least provide a better error message. Can you create an Issue for this?
I definitely can. What would you like me to name it? Also do I list any additional info that is not in this issue?
I think "SSH connection fails ssh command look up without default runspace". No more info is needed, just mention that this happens when hosting SMA.dll. Please assign to me.
@iSazonov @PaulHigin , I don't appear to have the ability to assign issues to people. Could one of you two do this for me? Sorry for the inconvenience. Issue #7763
@arahja Will do. BTW did you verify that this fixes your problem?
Yes, It does. Thank you for your assistance with this!
Leave a comment