How to run a command in terminal and capture the output - c#

I am working on an application using MonoDevelop in Ubuntu. Through this application I need to run a terminal command and capture it's output. Is such thing possible? Any help/ideas will be appreciated!
What I mean is, if user clicks on a button, the command will be run and the output will be displayed in a text box or something. I don't want a terminal window pop-up, this action should be entirely done inside the application.

In C# Windows you would do this:
Process p = new Process(); // Redirect the output stream of the child process.
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "program.exe";
p.Start(); // Do not wait for the child process to exit before reading to the end of its redirected stream.
p.WaitForExit(); // Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

Related

Why does redirecting standard input result in stdout not being printed to a new console process?

So I am attempting to run a separate program, using Process.Start().
The program will pause occasionally and wait for input. I wish to be able to send information to this process on standard input.
I am trying to make sense of the difference between creating a new process using the windows OS shell and the effects of redirecting standard input.
Exe UseShell RedirectSTDIN WINDOW Displays OutputDisplays
cmd.exe /c program Y N Y Y
N N Y Y
N Y Y N
program.exe Y N Y Y
N N Y Y
N Y Y N
The important information is just that if I redirect standard input, then no data displays to the screen.
Why is this the case?
Normally program.exe should be writing to its stdout file descriptor.
I assume that Process.Start() creates a console process. According to
MSDN:
Creating a new console results in a new console window, as well as separate I/O screen buffers.
I assume that this new window contains the console and displays the data in the console buffer. Thus, if the program outputs to stdout, we should see that data on the screen.
This is what happens normally. Why does redirecting standard input result in nothing being displayed on the screen, even though I do not touch redirect standard output?
edit:
startInfo.WindowStyle = ProcessWindowStyle.Normal;
//startInfo.FileName = Path.Combine(BinaryDirectory, "program.exe");
startInfo.FileName = "cmd.exe";
startInfo.CreateNoWindow = false;
//startInfo.Arguments = "";
startInfo.Arguments = "/C program.exe" + startInfo.Arguments;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
According to the documentation here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681953(v=vs.85).aspx
A process can use the AttachConsole function to attach to a console. A process can be attached to one console. A console can have many processes attached to it.
I thought that my process could just hook onto the console used by the simulator and then I could write to the console. However, it returns error code 6: the console handle is invalid.
So I got it working using Harry Johnson's method:
cmd.exe /c program.exe >CON 2>&1
I also believe that I could easily create my own window, hide the window for the process and direct output to that new window.
I just wanted to be able to write to the window that the process is in. But I haven't found any way to do that. I can attach to the console of that process. But to write to that process, I require the console's screen buffer

How can I open an external Java console application with arguments, capture output and execute commands on it?

I have a Java .jar application that is ran from a .bat file to have arguments passed to the Java application. The application opens a console (cmd.exe to be exact), writes things to it regularly and accepts some commands. I'm trying to create a kind-of wrapper around it in C# Winforms to ease it's use. How can I run the .jar with the same arguments as are in the .bat file, capture realtime output and write execute commands?
Yes, it is possible to do this using the System.Diagnostics.Process class and the ProcessStartInfo class from the .NET Framework. The Process class is used to control (start / stop) the desired process (application) and the ProcessStartInfo class is used to configure the process instance that will be started (arguments, redirect input and output, show / hide process window, and so on).
The code for starting a jar file looks like this:
var jarFile = "D:\\software\\java2html\\java2html.jar");
// location of the java.exe binary used to start the jar file
var javaExecutable = "c:\\Program Files (x86)\\Java\\jre7\\bin\\java.exe";
try
{
// command line for java.exe in order to start a jar file: java -jar jar_file
var arguments = String.Format(" -jar {0}", jarFile);
// create a process instance
var process = new Process();
// and instruct it to start java with the given parameters
var processStartInfo = new ProcessStartInfo(javaExecutable, arguments);
process.StartInfo = processStartInfo;
// start the process
process.Start();
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
The usual way to start a jar file is:
java -jar file.jar
To be sure, that the process will find the (in this case java) executable, it is a good practice to specify the fully qualified path to the process you want to start.
In order to redirect the standard output of the application you are starting, you need to set the ProcessStartInfo.RedirectStandardOutput property to true and then use the Process.StandardOutput property stream to fetch the output of the started application. The modified code for the application from the example above looks like this:
// command line for java.exe in order to start a jar file: java -jar jar_file
var arguments = String.Format(" -jar {0}", jarFile);
// indicate, that you want to capture the application output
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
// create a process instance
var process = new Process();
// and instruct it to start java with the given parameters
var processStartInfo = new ProcessStartInfo(javaExecutable, arguments);
process.StartInfo = processStartInfo;
// start the process
process.Start();
// read the output from the started appplication
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
If you want to control the input too, set the ProcessStartInfo.RedirectStandarInput property to true and then use the Process.StandardInput property stream to send input data to the started application.

run shell command for third party application, pass file arguements

I'm trying to edit my own shell command to include another shell command from another application, namely AxCrypt. In a sense I'm trying to merge two context menu actions into one. If I right-click on a file, I go to AxCrypt and choose "Encrypt file to .EXE". Then I right-click again on the encrypted file and choose my shell command.
The reason I'm being so specific is someone may have something like this already. I have added this:
try
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = true;
proc.StartInfo.FileName = #"C:\Program Files\Axantum\AxCrypt\AxCrypt.exe";
proc.Start();
MessageBox.Show("AxCrypt run");
}...
I get my messagebox, but the AxCrypt application doesn't run. any ideas on how to
determine if the executable i've entered is the right one for the context menu selection in windows
correctly run this process and feed it the file argument for the file that i clicked on (as if i had chosen their menu item from the context menu)
correctly word a message to send to AxCrypt on what i'm trying to do!
1. determine if the executable i've entered is the right one for the
context menu selection in windows
Run ProcessMonitor and check the path used to launch the exe is correct - otherwise you'll see whats wrong.
2. correctly run this process and feed it the file argument for the
file that i clicked on (as if i had chosen their menu item from the
context menu)
string args = String.Format(#"{0}", "A File Arg");
proc.StartInfo.Arguments = args;
3. correctly word a message to send to AxCrypt on what i'm trying to
do!
Send them a link to this SO Q & A
I had the same problem. Look this:
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
pProcess.StartInfo.FileName = #"C:\Users\Vitor\Documents\Visual Studio 2015\Projects\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe";
pProcess.StartInfo.Arguments = "olaa";
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
pProcess.StartInfo.CreateNoWindow = true;
pProcess.Start();
string output = pProcess.StandardOutput.ReadToEnd();
pProcess.WaitForExit();

Unlock section in applicationHost.config programmatically

I have checked ServerManagaer class and it gives a lot of functionality to work with IIS, it also contains methods to update values in applicationHost.config file, but I can't fine any way to unlock sections there.
For example for that purpose appcmd.exe unlock config command is used. I need to do the same programmatically.
As already said you can run appcmd process. But just a hint that if you don't console to popup you can redirect the output.
Here is the code from MSDN
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
More details see HERE
To my knowledge you can't perform lock/unlock action using ServerManager but still you can execute appcmd.exe programatically to achieve the desired result:
System.Diagnostics.Process appCmdProc = new System.Diagnostics.Process();
appCmdProc.StartInfo.FileName = "Path-to-Directory\appcmd.exe";
appCmdProc.StartInfo.Arguments = "unlock config /section:sectionName";
appCmdProc.Start();

Process.WaitForExit() on Console vs Windows Forms

I have a console app and a win forms app that both need to call out to a remote server for some data, they make a call to the command line part of Putty, plink.exe, to run a remote command over SSH.
I created a tiny class library for both to share, running the following:
public static string RunCommand(string command, string arguments) {
ProcessStartInfo startInfo = new ProcessStartInfo {
FileName = command,
Arguments = arguments,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true
};
string output = null;
using (Process p = new Process()) {
p.StartInfo = processStartInfo;
p.Start();
output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
return output;
}
Under the console application everything works fine, under the win forms it doesn't error, it seems that WaitForExit() just doesn't wait. I get an empty string for output. I've confirmed from the remote server the user logged in, so it seems the command has run.
Any ideas?
Under Windows Console applications have STDIN, STDOUT, and STDERR. Windowed applications do not. When you create a process under a Console application the STDIN etc. are inherited by the child application. This does not happen in the Windowed application.
The RedirectStandardInput=true works because it makes the system create a Writer for the STDIN that you can use to send input to the child process. In your case the child doesn't need the input it just needs the presence of the input. YMMV.

Categories