Copying CMD output to clipboard - c#

I'm trying to copy output from a program running out of the CMD prompt to the Windows clipboard.
private void button1_Click(object sender, EventArgs e)
{
/*Relevant Code*/
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = String.Format("/k cd {0} && backdoor -rt -on -s{1} -p{2}", backdoorDir, pSN, sPPC);
p.Start();
p.WaitForExit();
string result = p.StandardOutput.ReadToEnd();
System.Windows.Forms.Clipboard.SetText(result);
}
If I were to enter this directly into CMD, it would look like this:
First Command (change directory):
cd C:\users\chris\appdata\roaming\backdoor
Second Command (Launches backdoor, a cmd tool. Arguments follow.):
backdoor -rt -on -sCCDXE -p14453
And when doing this through CMD, I get this result:
The backdoor password is: 34765
C:\users\chris\appdata\roaming\backdoor>
However, when running my C# code, this is the only thing that gets added to my clipboard:
C:\users\chris\appdata\roaming\backdoor>
Why isn't it capturing "The backdoor password is: 34765?" It's like the p.StandardOutput.ReadToEnd() isn't reading everything.

Call ReadToEnd before WaitForExit
Chris' code:
private void button1_Click(object sender, EventArgs e)
{
/*Relevant Code*/
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = String.Format("/k cd {0} && backdoor -rt -on -s{1} -p{2}", backdoorDir, pSN, sPPC);
p.Start();
string result = p.StandardOutput.ReadToEnd();
p.WaitForExit();
System.Windows.Forms.Clipboard.SetText(result);
}
Sample console app code:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/C dir";
p.Start();
string result = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(result);
Console.ReadLine();
argument /C executes the command and then terminates the cmd process. This is necessary for this code to work. Otherwise, it will wait for ever.

One reson may well be that the program is not actually writing to StdOut but to the screen directly.
Test this by piping the output into a file:
backdoor -rt -on -sCCDXE -p14453 > c:\text.txt
If the new file doesn't contain the output either then you are stuck and may need to look into screen scraping..

Related

Start process and get its output constantly

I have a console program written in c++, and I would like to continually check its output to use in my c# project.
This is the code I've tried to steal from another StackOverflow question, but with no luck.
Edit:( By no luck, I mean: the output is pretty much empty, although if I set p.StartInfo.CreateNoWindow to false, I can see my script.exe launch and output into its window. )
Process p = new Process();
p.StartInfo.FileName = #"external\script.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine("Output:");
Console.WriteLine(output);
I had a similar issue and it had to do with where the output was going. The solution was to run cmd and execute my script from the cmd process. See this answer to another question for more information. reading from stdout and stderr together Your new code would look like:
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c yourscriptpath.exe 2>&1";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine("Output:");
Console.WriteLine(output);

output limitation when calling exe file from c# code

I have an exe file that I call it from my c# code by using Process namespace in c#.
I catch output by using ReadToEnd() method. (in exe source code i used a print method for my desired output).
the problem is when my output is getting larger the executing of exe file is got crashed and hanged.
Is there any limitation of output size when calling exe function?
Process p = new Process();
p.StartInfo.FileName = command;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.Arguments = args;
p.Start();
p.WaitForExit();
string output = p.StandardOutput.ReadToEnd();
return output;
What you're experiencing is a deadlock. That situation is described in the documentation. In order to avoid it, make sure you read the output before waiting for the child process to exit.
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
I remember having the same problem as you're describing here, and what I did back then was something like this:
private string RunProcess(string command, string args)
{
StringBuilder sb = new StringBuilder();
Process p = new Process();
p.StartInfo.FileName = command;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.Arguments = args;
p.OutputDataReceived += (sender, eventArgs) => { sb.Append(eventArgs.Data); };
p.Start();
p.WaitForExit();
return sb.ToString();
}

How to auto fill cmd prompt

I Have a C# program; when I hit a button I want it to open a CMD window, then automatically type in the cmd window and run that said command. So far I have this from 4 hours of research. But nothing is working.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
//p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine("ipconfig");
Any idea on how to fill in a certain text then automatically run it when the button is hit?
With StandardInput and StandardOutput redirected, you cannot see the new window opened. If you want to create a new cmd window and run ipconfig in it, you could do this:
var p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c ipconfig & pause";
p.Start();
I agree that if all you want to do is execute "ipconfig" you could just invoke it instead of cmd.exe. Assuming you want to do other things with cmd.exe, here is an example of how to invoke it, have it execute a command, and then terminate (using the /K switch instead of /C will keep cmd.exe running):
using System;
using System.Diagnostics;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/C ipconfig";
p.Start();
var output = p.StandardOutput.ReadToEnd();
Console.Write(output);
Console.ReadKey();
}
}
}

Redirecting Output from Cmd Prompt

New to programming and I'm writing a process which is supposed to open up the cmd prompt, run the command
"/k nslookup 123.123.123.123;
And then redirect the standard output into a string so the data can be manipulated. I've tried various combinations but cannot get the program to output anything except my last line of "Press any key to close".
I feel as though I'm missing something very simple as I can't find anything wrong with my code. Does anyone have any suggestions?
try
{
string strCmdText;
strCmdText = "/k nslookup 123.123.123.123";
// Start the process.
Process p = new Process();
//The name of the application to start, or the name of a document
p.StartInfo.FileName = "C:/Windows/System32/cmd.exe";
// On start run the string strCmdText as a command
p.StartInfo.Arguments = strCmdText;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadLine();
p.WaitForExit();
Console.WriteLine(output);
}
catch (Exception)
{
Console.WriteLine( "error");
}
//Wait for user to press a button to close window
Console.WriteLine("Press any key...");
Console.ReadLine();
I think it is because the command prompt is not exiting. Instead of passing arguments, write them to the standard input and then exit, like this:
p.StartInfo.Arguments = "";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine("/k nslookup 123.123.123.123");
p.StandardInput.WriteLine("exit");
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);

stderr in the shell and a copy into log file

I use the Process class to run pscp.exe (from Putty) in my WPF C# application like this:
Process p = new Process();
p.StartInfo.FileName = "pscp.exe";
p.StartInfo.Arguments = "-v -scp -pw xx toto#192.168.0.1:/path .";
p.Start();
p.WaitForExit();
The process opens a command prompt and exit correctly, it's ok.
Now, I would like to log in a file the stderr of the process, no problem, I use:
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
and I print the stream in my file, but nothing is shown in the shell (it's ok this is a redirection).
My needs is to show the stderr in the shell AND copy it to my log file (no redirection, I wanted twice).
EDIT: A clear exemple that represent my need:
Imagine a WPF application with one button which call this function:
Process p = new Process();
p.StartInfo.FileName = "pscp.exe";
p.StartInfo.Arguments = "-v -scp -pw xx toto#192.168.0.1:/path .";
p.Start();
p.WaitForExit();
The process starts with a cmd prompt (print stdout + stderr in it) and at the same time stderr is printed in a log file.
Any idea to do this ?
You need to subscribe to the ErrorDataReceivedEvent
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.errordatareceived.aspx
Process p = new Process();
p.StartInfo.FileName = "pscp.exe";
p.StartInfo.Arguments = "-v -scp -pw xx toto#192.168.0.1:/path .";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.ErrorDataReceived += (o, e) => Console.Error.WriteLine(e.Data);
p.Start();
p.WaitForExit();
As described by Hylaean: First you prepare your Process object and register the event(s):
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.ErrorDataReceived += new DataReceivedEventHandler(shell_ErrorDataReceived);
p.OutputDataReceived += new DataReceivedEventHandler(shell_OutputDataReceived);
shellOut = openWriter(outputFileName); // opens a StreamWriter
In the event handlers, you can do what you like with the stderr and stdout data:
// write out info to the display window
private static void shell_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
string s = e.Data;
if ((s != null) && (shellOut != null))
{
SomeOutOrLog(s); // output or log the string to somewhere
shellOut.WriteLine(s);
}
}
private static void shell_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
string s = e.Data;
if (s != null)
{
SomeOutOrLog(s); // output or log the string to somewhere
}
}

Categories