cantas
cantas

Reputation: 114

How to get output of the cmd?

I want to get output of the cmd result in a string

void getDevices()
{
      Process p = new Process();
      ProcessStartInfo proc = new ProcessStartInfo();
      proc.FileName = @"C:\Users\mehmetcan\Desktop\adt-bundle-windows-x86-20130917\sdk\platform-tools\adb.exe";
      proc.Arguments = @"devices";
      Process.Start(proc);
      String output = p.StandardOutput.ReadToEnd();           
}

Error: An unhandled exception of type 'System.InvalidOperationException' occurred in System.dll

Upvotes: 3

Views: 1380

Answers (2)

zeluisping
zeluisping

Reputation: 224

You have to give your process a ProcessStartInfo that tells it you're going to be reading the output.

Here is an example:

ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = @"C:\Users\mehmetcan\Desktop\adt-bundle-windows-x86-20130917\sdk\platform-tools\adb.exe";
startinfo.Arguments = @"devices";
startinfo.RedirectStandardOutput = true;
startinfo.RedirectStandardError = true;

// Note: declare process as a variable in the class as it needs to be used in the event handlers
process = new Process();
process.StartInfo = startinfo;

process.OutputDataReceived += process_DataReceived;
process.ErrorDataReceived += process_DataReceived;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();

And then the event hander that receives the data (this is called each time the process outputs something):

private void process_DataReceived(object sender, DataReceivedEventArgs e)
{
    // null data means we've received everything
    if (e.Data == null) {
        process.CancelOutputRead();
        process.CancelErrorRead();
        return;
    }

    // e.Data is the string with the output from the process
    Console.Write(e.Data);
}

Note that process_DataReceived is called whenever the process outputs something, if what you need is to get the complete output, then you can do this:

process_output = ""; // reset output before starting the process

ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = @"C:\Users\mehmetcan\Desktop\adt-bundle-windows-x86-20130917\sdk\platform-tools\adb.exe";
startinfo.Arguments = @"devices";
startinfo.RedirectStandardOutput = true;
startinfo.RedirectStandardError = true;

Process process = new Process();
process.StartInfo = startinfo;

process.OutputDataReceived += process_DataReceived;
process.ErrorDataReceived += process_DataReceived;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();

// check end of answer if you need to wait for the process to terminate

Declare a string variable that is available to both process_DataReceived and to process_Exited, for example a variable in the class that contains the methods:

string process_output; // will accumulate the output of the process

And then the event handlers:

private void process_DataReceived(object sender, DataReceivedEventArgs e)
{
    // null data means we've received everything
    if (e.Data == null) {
        process.CancelOutputRead();
        process.CancelErrorRead();

        // do something with the output:
        Console.Write(process_output);

        return;
    }

    // append the output to the accumulator
    process_output += e.Data;
}

After the process exits, you can still receive output data, therefore if you need to wait for the process to finish, you can add a flag (a boolean) and set it to false only when you receive null data in process_DataReceived. You can only be sure you've received all of the output from the process when that happens.

Access UI From 'process_DataReceived'

If you have to access a UI element from process_DataReceived you can do so by using it's dispatcher. Here is an example:

private void process_DataReceived(object sender, DataReceivedEventArgs e)
{
    // null data means we've received everything
    if (e.Data == null) {
        process.CancelOutputRead();
        process.CancelErrorRead();

        // with WPF:
        mylabel.Dispatcher.Invoke(new Action(() => {
            mylabel.Content = process_output;
        }));

        // with WinForms
        mylabel.Invoke((MethodInvoker) (() =>
        {
            mylabel.Text = process_output;
        }));

        return;
    }

    // append the output to the accumulator
    process_output += e.Data;
}

Upvotes: 4

Rahul Tripathi
Rahul Tripathi

Reputation: 172378

How about trying like this:-

public static void Main()
    {
        ProcessStartInfo proc = new ProcessStartInfo();
        proc.FileName = @"C:\Users\mehmetcan\Desktop\adt-bundle-windows-x86-20130917\sdk\platform-tools\adb.exe";
         proc.Arguments = @"devices";

        Process p = Process.Start(proc);
        p.OutputDataReceived += (sender, e) => Console.WriteLine(e.Data);
        p.BeginOutputReadLine();
        p.Start();
        p.WaitForExit();
        Thread.Sleep(5000);
    }

Also check Process.OutputDataReceived and Process.BeginOutputReadLine

Upvotes: 1

Related Questions