how to open a putty session using C# - c#

I would like to know how to open putty using C# in Visual Basic express. Then execute commands through the ssh session.

You can use plink.exe for SSH an pscp.exe for SCP.
https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
Donwload the 2 files, then copy them into your Solution. Then under Properties select: Copy if newer.
// SCP
var process = new Process();
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = Directory.GetCurrentDirectory() + $#"\pscp.exe";
processStartInfo.Arguments = $#"-P 22 -pw password filepath.zip root#host:/path ";
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.CreateNoWindow = true;
process.StartInfo = processStartInfo;
process.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);
process.ErrorDataReceived += (sender, args) => Console.WriteLine(args.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
Console.WriteLine(process.ExitCode);
// SSH
process = new Process();
processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = Directory.GetCurrentDirectory() + $#"\plink.exe";
processStartInfo.Arguments = $#"-P 22 -pw password root#host command";
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.CreateNoWindow = true;
process.StartInfo = processStartInfo;
process.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);
process.ErrorDataReceived += (sender, args) => Console.WriteLine(args.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();

I recently had to do something similar with WinSCP and the way I did it was to kick off the process with redirected Standard Input and Output. If Putty use the the standard input/output you might be able to use the same method for that.
The sample on the WinSCP pages is quite good so I'd suggest starting with that, and here's a code project article about something similar: How to redirect Standard Input/Output of an application

What you actually need is an SSH component for .NET, capable of providing shell and command channel access to the remote host. Shell is what you see with PuTTY. You "type" the requests and get some response, which you need to parse then to separate responses from command prompt. Command channel is when the commands are sent one by one and you receive only response(s) back. You don't need to parse anything (besides handling actual responses). Simple components can't send multiple commands in one session.
You can take our SSH component for .NET, that offers both shell and command channels, and supports many types of authentication (so it doesn't matter what authentication type your server uses - our component supports it).

Related

Capture output written directly to Windows console

I'm trying to capture the output of a Windows executable that's executed from C#. Currently, this is what I have:
private static string Execute(string pathToExe, string pathToInputFile, string pathToOutputFolder)
{
var standardOutput = new StringBuilder();
var errorOutput = new StringBuilder();
var process = new System.Diagnostics.Process();
process.StartInfo.FileName = pathToExe;
process.StartInfo.Arguments = $"\"{pathToInputFile}\" \"{pathToOutputFolder}\"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += (sender, eventArgs) => standardOutput.AppendLine(eventArgs.Data);
process.ErrorDataReceived += (sender, eventArgs) => errorOutput.AppendLine(eventArgs.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit(-1);
return standardOutput.ToString() + errorOutput.ToString();
}
Instead of returning the console output of the executable, I'm only getting a blank string. Instead, the output is being written to my application's console.
I believe this is because the executable I'm running actually launches a GUI program. When run from the command line, the app exposes a CLI. It's my guess that the application is attaching itself to the current console instead of attaching to a new one that's monitored by my application.
For example, running the following in PowerShell 7 results in the output still being written to the console, as opposed to being redirected to the output.txt file:
external.exe --help *> output.txt
So it seems the executable isn't writing to one of the standard output streams.
Does anyone have any ideas or workarounds that would work in .NET Core 3.1 on Windows?

Stop process output from being displayed in project command window

I'm starting an exe via the Process class and I've noticed that the exe's output is being displayed inside my application's command window. *Note - when I start up the exe, I make sure a window is not opened - so, the only window that displays when my application is running is my main application, project.exe.
Is there a way to stop the exe's output from being displayed inside my project.exe command window? Here is my code:
Process process = new Process();
string exePath = System.IO.Path.Combine(workingDir, exeString);
process.StartInfo.FileName = exePath;
process.StartInfo.WorkingDirectory = workingDir;
process.StartInfo.Arguments = args;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (s, e) => Logger.LogInfo(e.Data);
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
I've even tried setting RedirectStandardOutput to false with:
process.StartInfo.RedirectStandardOutput = false;
and the output is still placed in the command window.
This works when I tried locally on my box. Can you give it a try by replacing the exe path/name.
From MSDN doc's.
"When a Process writes text to its standard stream, that text is typically displayed on the console. By setting RedirectStandardOutput to true to redirect the StandardOutput stream, you can manipulate or suppress the output of a process. For example, you can filter the text, format it differently, or write the output to both the console and a designated log file"
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx
void Main()
{
Process process = new Process();
string exePath = System.IO.Path.Combine(#"C:\SourceCode\CS\DsSmokeTest\bin\Debug", "DsSmokeTest.exe");
process.StartInfo.FileName = exePath;
process.StartInfo.WorkingDirectory = #"C:\SourceCode\CS\DsSmokeTest\bin\Debug";
process.StartInfo.Arguments = string.Empty;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (s, e) => Test(e.Data);
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
}
// Define other methods and classes here
public void Test(string input)
{
input.Dump();
}
just add the following line
process.StartInfo.UseShellExecute = true;

How to send commands to cmd in C#

I am coding a program in C# and I need to open cmd.exe, send my commands and get its answers.
I searched around and found some answers to take diagnostics.process in use.
Now, I have two problems:
When I get the output of process, the output is not shown on the cmd consoule itself.
I need to call g95 compiler on the system. When I call it from cmd manually, it is invoked and does well, but when I call it programmatically, I have the this error: "g95 is not recognized as an internal or external ..."
On the other hand, I only found how to send my commands to cmd.exe via arguments and process.standardInput.writeline(). Is there any more convenient method to use. I need to send commands when the cmd.exe is open.
I am sending a part of my code which may help:
System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
myProcess.StartInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe");
//myProcess.StartInfo.Arguments = "/c g95";
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(myProcess_OutputDataReceived);
myProcess.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(myProcess_ErrorDataReceived);
myProcess.Start();
myProcess.BeginOutputReadLine();
myProcess.BeginErrorReadLine();
myProcess.StandardInput.WriteLine("g95 c:\\1_2.f -o c:\\1_2.exe");
You can specify the g95 directly and pass the desired command line parameters to it. You don't need to execute cmd first. The command may not be regognized because the settings from the user profile are not loaded. Try setting the property LoadUserProfile in StartInfo to true.
myProcess.StartInfo.LoadUserProfile = true;
This should also set the path variables correctly.
Your code would look something like this:
Process myProcess = new Process();
myProcess.StartInfo = new ProcessStartInfo("g95");
myProcess.StartInfo.Arguments = "c:\\1_2.f -o c:\\1_2.exe"
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.LoadUserProfile = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.OutputDataReceived += myProcess_OutputDataReceived;
myProcess.ErrorDataReceived += myProcess_ErrorDataReceived;
myProcess.Start();
myProcess.BeginOutputReadLine();
myProcess.BeginErrorReadLine();
You are getting the error
"g95 is not recognized as an internal or external ..."
because you haven't added the path to g95.exe in your PATH environment variable. You will get similar result if you open up command prompt and type g95. Here is a link to G95 Windows FAQ page that explains it.

Process class db2cmd c#

I have my program which needs to run a ".BAT" file in IBM DB2 (db2cmd.exe). And log the contents of that console into a string, which I should be able to format.
Status quo is:
The bat file contains username and password to the database, Export to csv query. The bat file when executed manually works absolutely fine.
The problem is that I am not able to capture the details of that console into a string.
Code snippet is as follows:
proc.StartInfo.FileName = "db2cmd.exe";
proc.StartInfo.Arguments = #"C:\test.bat";
proc.StartInfo.WorkingDirectory = #"C:\Program Files\IBM\SQLLIB\BIN\";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.OutputDataReceived += (o, e) => s.AppendLine(e.Data);
proc.ErrorDataReceived += (o, e) => s.AppendLine(e.Data);
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
code = proc.ExitCode;
db2cmd.exe opens a new command shell by default. Try using the command switches /i /c to run your script in the same shell.
Using -i option with db2cmd.exe should fix this issue. Modify first line of your program as below:
proc.StartInfo.FileName = "db2cmd.exe -i";

Executing "java -version" programmatically places the output in StandardError instead of StandardOutput

I am facing very strange behavior as I am trying to programmatically detect the java version on my PC. I am using the following C# code:
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c java -version");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
Process proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
output = proc.StandardOutput.ReadToEnd();
if (output == "")
output = proc.StandardError.ReadToEnd();
return output;
This displays the correct information but the result is found in proc.StandardError.ReadToEnd() instead of proc.StandardOutput.ReadToEnd() as in any other command (i.e. 'java -help').
Even more weird, if I run "java -showversion" which should output both java version and then help information I get the help info in the StandardOutput and the version info is in the StandardError.
This doesn't make sense to me.
I tested this on 2 Windows 7 x64 machines and 1 XP x32. Same thing everywhere. It's really weird.
Looks likes this (i.e. version being printed on standard out) is an old issue that sun (oracle) has never fixed in order to avoid breaking legacy systems: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4380614. On linux, java -version > foo will create an empty file while java -version 2> foo will create a file containing the version.
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c java -version");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
Process proc = new Process();
proc.StartInfo = procStartInfo;
proc.EnableRaisingEvents = true;
// create event and wait for data receive
proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
proc.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
static void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
string s = e.Data;
}
static void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
string s = e.Data;
}
This should do the trick:
java -version 2>&1 | more
"more" is not required, unless you want to redirect it to file for example.
Works both on *NIX and Win.

Categories