I would like to connect use ssh to connect to an other computer. Following you can see my code.
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = #"C:\Program Files (x86)\PuTTY\putty.exe";
startinfo.Arguments = "-ssh <user>#<domain> -pw <password>";
Process process = new Process();
process.StartInfo = startinfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.StandardInput.WriteLine("<command>");
process.WaitForExit();
Console.ReadKey();
With that I have two problems. Firstly, the command should wait until the connection is successful established. Secondly, the command is not shown in the cmd. I don't know if don't see the commands because it's not waiting until the connection is successful or it is just not working.
I really appreciate any help.
Using the GUI application "Putty" to initiate a ssh connection is not optimal. First of all, Putty just gives you a messagebox with an error in it on an unsuccesfull connection attempt, e.g.
In your program-logic, you have no way of reacting to this event, since everything is handled by Putty and nothing is written to stdout or stderr. Also, the program hangs until the user clicks a button when such an error occures, thus requiring user interaction to even get the program to exit. I'm not sure wether Putty even gives you a meaningfull exitcode after the user closes the window, which you can use after the execution of the program.
So, all you could do is hope for the connection to be successfull. But you get no reaction on when the connection has been established. The best shot you have is doing a Thread.Sleep() for a while, then writing into stdin. I'm not sure wether you can control what Putty shows in the GUI through stdin (it doesn't seem to show up according to your information) or stdout.
Overall, starting a Putty process to establish an ssh connection is the wrong approach. You should look at external libraries such as https://sshnet.codeplex.com/ or the C# WinSCP library and the Session.ExecuteCommand() method. It should be as easy as shown in the code here. Using C# libraries, you also have a much, much better control over handling connection errors, timeout errors, command execution errors and reacting on command outputs.
Related
I have a Windows console application that is launched via a schedule setup in Task Scheduler. This console application, as part of its normal runtime, will launch a command prompt in order to run a java program. No, I have no control over the design of the Java program. It was supplied to me as is and I have no rights or access to make changes to it. I also cannot implement it in another language. I must use what was given to me.
At any rate, when my console application tries to run the command prompt it will work just fine if I'm launching the application manually. However, when I try it as an action within Task Scheduler, my console application will start and run as expected until it needs to launch the command prompt. At this point, the console application exits. No error message or code is provided.
How do I get the command prompt window to start as a new window from within my console application when no one is logged into the server?
Thanks for any hints or suggestions you can provide.
* UPDATE *
Here is the code snippet that launches the program from within my console application:
string parameter_save_path = #"C:\output\folder"
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo start_info = new System.Diagnostics.ProcessStartInfo();
start_info.WorkingDirectory = #"C:\mtselect-client";
start_info.FileName = "cmd.exe";
start_info.Arguments = "/C run.bat \"" + parameter_save_path + "\"";
process.StartInfo = start_info;
process.Start();
process.WaitForExit();
The run.bat is what launches the java program.
I think it's too late for this message, but...
Maybe in your batch file you are running your java application with something like: java -jar ApplicationName
First I would do should be comment out the "#echo off" from the batch file, next trace out the batch lines with one echo "x" (being x a natural number starting from 1 and increasing by 1 in each ocurrence). Next I will add a line with java -version, and so I will be sure java app is installed and accesible.
Maybe java needs be ran by an authenticated user and so have java_home defined. Maybe the application needs some JVM parameters like memory size, etc.
Have good luck, tell me and I will try to help
This question already has answers here:
Run Unix commands using PuTTY in C# [duplicate]
(2 answers)
Closed 3 years ago.
Hi I have the below code,
I am able to open putty session but i was not able to give the inputs using C# , i have tried using process.StandardInput.WriteLine but it is not working . Please help me.
class Program
{
static void Main(string[] args)
{
Process process = new Process();
process.StartInfo.FileName = #"C:\Users\win7\Desktop\putty.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.Arguments = "-ssh mahi#192.168.37.129 22 -pw mahi";
process.Start();
process.StandardInput.WriteLine("ls");
}
}
Hi All , I Have used Plink instead of putty by the suggestion given by Onots.
I have done the following
1.Edited my path in environment variable to my plink location i.e., D:\Plink\
2.Manually Opened Command Prompt and Logged into my host server using plink using the command
plink-0.57.exe -ssh mahi#192.168.37.129 -pw mahi and i am able to execute commands manually.
3.Now i have modified the code as below
class Program
{
static void Main(string[] args)
{
Process process = new Process();
process.StartInfo.FileName = #"D:\Plink0.57\plink-057.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.Arguments = " -ssh mahi#192.168.37.129 -pw mahi";
process.Start();
process.StandardInput.WriteLine("ls");
}
}
But i was not able to open plink and the command is not executing using C#. But what happens is , a command prompt just appears and closes immediately , i have figured the error message as
"Unable to write to standard input"
Please help me ,i am not able to proceed any further. Thanks In Advance.
Wouldn't it be easier to use the command line Plink (PuTTY Link) instead of the GUI? I believe that it is more suitable for automated tasks.
See http://the.earth.li/~sgtatham/putty/0.63/htmldoc/Chapter7.html#plink for example usage.
I will quote the relevant part here, just in case the link goes bad:
7.2.2 Using Plink for automated connections
More typically Plink is used with the SSH protocol, to enable you to
talk directly to a program running on the server. To do this you have
to ensure Plink is using the SSH protocol. You can do this in several
ways:
Use the -ssh option as described in section 7.2.1. Set up a PuTTY
saved session that describes the server you are connecting to, and
that also specifies the protocol as SSH. Set the Windows environment
variable PLINK_PROTOCOL to the word ssh. Usually Plink is not invoked
directly by a user, but run automatically by another process.
Therefore you typically do not want Plink to prompt you for a user
name or a password.
Next, you are likely to need to avoid the various interactive prompts
Plink can produce. You might be prompted to verify the host key of the
server you're connecting to, to enter a user name, or to enter a
password.
To avoid being prompted for the server host key when using Plink for
an automated connection, you should first make a manual connection
(using either of PuTTY or Plink) to the same server, verify the host
key (see section 2.2 for more information), and select Yes to add the
host key to the Registry. After that, Plink commands connecting to
that server should not give a host key prompt unless the host key
changes.
To avoid being prompted for a user name, you can:
Use the -l option to specify a user name on the command line. For
example, plink login.example.com -l fred. Set up a PuTTY saved session
that describes the server you are connecting to, and that also
specifies the username to log in as (see section 4.14.1). To avoid
being prompted for a password, you should almost certainly set up
public-key authentication. (See chapter 8 for a general introduction
to public-key authentication.) Again, you can do this in two ways:
Set up a PuTTY saved session that describes the server you are
connecting to, and that also specifies a private key file (see section
4.20.8). For this to work without prompting, your private key will need to have no passphrase. Store the private key in Pageant. See
chapter 9 for further information. Once you have done all this, you
should be able to run a remote command on the SSH server machine and
have it execute automatically with no prompting:
Z:\sysosd>plink login.example.com -l fred echo hello, world hello,
world
Z:\sysosd> Or, if you have set up a saved session with all the
connection details:
Z:\sysosd>plink mysession echo hello, world hello, world
Z:\sysosd> Then you can set up other programs to run this Plink
command and talk to it as if it were a process on the server machine.
The following code gives the solution
class Program
{
static void Main(string[] args)
{
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = #"D:\Plink0.57\plink-057.exe";
startinfo.Arguments = "-ssh mahi#192.168.37.129 -pw mahi";
Process process = new Process();
process.StartInfo = startinfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.StandardInput.WriteLine("ls");
process.WaitForExit();
Console.ReadKey();
}
}
So here's my problem:
Python scripts launched from C# via the Process class require the -i switch to be passed to python.exe or else they don't send any output when I redirect the StandardXxx streams
I want to bundle my Python program with py2exe (or another similar setup, if one meets my needs)
py2exe does not seem to let me pass the -i switch in any obvious way, but it's giving my the same issue as running python.exe - it doesn't output anything when launched by my C# program. So I need a way to force it into a similar mode so I can actually receive and send messages over stdin/stdout. I found some similar problems when it's built with "windows=['my_script']" but I built it with "console=['my_script']", so those fixes didn't help, and I don't need an actual interactive mode (i.e. the REPL), but for some reason the -i switch fixes the console IO issues.
This is the code I'm using to launch it:
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.FileName = "py2exe_program.exe";
Process p = Process.Start(psi);
// program hangs here because ready message is never printed
p.StandardOutput.ReadLine(); // Consume ready message
The executable works as expected when launched externally, and the above code works when I launch the Python script via "python.exe -i my_script.py" but it runs into the same problem without the -i switch.
How do I get it to behave as expected?
SHORT VERSION
How do you figure out which DLL is failing to load (and potentially why) when a process exits with error code -1073741502?
LONG VERSION
I'm trying to write a pretxnchangegroup hook for Mercurial, and as a part of that hook I need to get the output of running the command:
hg log
The code that I'm using to start and run the hg.exe process is as follows:
string Command = "log";
Process p = new Process();
ProcessStartInfo psi = p.StartInfo;
p.StartInfo.FileName = #"C:\Program Files (x86)\Mercurial\hg.exe";
psi.CreateNoWindow = true;
psi.LoadUserProfile = true;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.WorkingDirectory = Environment.CurrentDirectory;
p.StartInfo.Arguments = Command;
// Pass-through environment variables
psi.UserName = Properties.Settings.Default.HG_User;
psi.Domain = Properties.Settings.Default.HG_Domain;
psi.Password = new System.Security.SecureString();
foreach (char c in Properties.Settings.Default.HG_Pass)
{
psi.Password.AppendChar(c);
}
p.Start();
p.WaitForExit();
The problem is that the process keeps exiting with error code -1073741502, without outputting anything on Standard Output or Standard Error. After some research online, I discovered that this error code has something to do with the application failing to initialize properly (couldn't find DLL's, maybe?), but I have no idea how to go about figuring out how to fix it.
Keep in mind that this hook is being called for when I'm pushing to the repository over the web (so, IIS is calling the Mercurial CGI via Python, which has this program configured as a hook).
In a totally different web application, I'm able to run HG commands just fine, and I'm also able to run this by doing
runas /user:<same account as in the code> /noprofile cmd.exe and then manually typing in the hg command line.
Also, if I set UseShellExecute = true, then it executes just fine, but then I can't get the Standard Output. I'm really tempted to just make a web service call to the web app which is able to execute this command successfully, but that'd be a really ugly solution.
Any ideas why this thing isn't executing?
I was able to resolve this by disabling UAC so it sounds like a permissions problem even though I do not know the exact details.
I was always under the impression that when you're running a process as (domain\user) mydomain\myuser, when using Process.Start() it would start this new process using the same credentials - mydomain\myuser.
The issue I'm having is that my Process.Start() call seems to be creating a process under the SYSTEM account which is causing me permission issues in the started process (which must run under an admin account due to the work it does). If it changes things - I'm spawning this process (a custom built exe) from within a windows installer.
Any suggestions? I've read about windows group policies (possibly) having an impact on this, but if I'm honest, it's lost on me.
EDIT: a little snippet:
Where exename and commandLine are parameters for this method body:
ProcessStartInfo procInfo = new ProcessStartInfo(exeName, commandLine);
procInfo.WorkingDirectory = workingDirectory;
procInfo.UseShellExecute = false;
procInfo.CreateNoWindow = true;
Process process = Process.Start(procInfo);
Process.WaitForExit();
return process.ExitCode;
Either set procInfo.UseShellExecute to true, or execute cmd as a process with your exe as a parameter to the cmd command. When UseShellExecute is set to false, here are a lot of interesting side effects: UseShellExecute
Your impression is true. Process.Start() will always start the new process under current user's credentials - unless you provide alternative credentials in the ProcessStartInfo or use one of the overloads that take credentials.
There must be another problem - share a snippet of your code.
UPDATE
OK! You did not mention anything about installer. All MSI installers will be running under system since they will be run by "Windows Installer" which you can check and they run under SYSTEM.