Search code examples
c#androidwindowscommand-lineadb

How to wait for ADB output in C#?


I want to receive information from a device connected in USB via a C# program using ADB commands then flush the output.

Process process = new Process();
process.StartInfo.FileName = "adb.exe";
process.StartInfo.Arguments = "logcat -d -b main -v raw -s Command:I"; // get data in Log.I() with name == "Command"
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();

string output;
do {
    process.StandardInput.WriteLine("logcat -d -b main -v raw -s Command:I");
    output = process.StandardOutput.ReadToEnd();
} while (output.Length < 1);

Console.WriteLine(output);

process.StandardInput.WriteLine("logcat -c"); // flush logcat

process.WaitForExit();

Doing that I understand that the program is constantly executing adb logcat -d -b main -v raw -s Command:I, isn't there a way to call a command one time and wait for the output?

I can do that in windows prompt using :

adb shell 'logcat -b main -v raw -s UNIQUE_TAG:I | (read -n 1 && kill -2 $((BASHPID-1)))'

but is this doable in C#? Also the output doesn't seem to be flushed


Solution

  • Working code below, we don't call adb.exe directly but through cmd.exe with a command waiting for any information log coming from logcat with the title "Command" : adb shell logcat -b main -v raw -s Command:I

    private Process listeningProc;
    
    public someClass(){
       listeningProc = new Process();
       listeningProc.StartInfo.FileName = "cmd.exe";
       listeningProc.StartInfo.UseShellExecute = false;
       listeningProc.StartInfo.RedirectStandardOutput = true;
       listeningProc.StartInfo.RedirectStandardInput = true;
       listeningProc.Start();
    
       listeningProc.OutputDataReceived += new DataReceivedEventHandler(
           (s, e) => {
               if (e.Data == "SPECIFIC_COMMAND") {
                   // do something
               }
           }
       );
       listeningProc.BeginOutputReadLine();
    }
    
    private void ListenToCommands(){
       listeningProc.StandardInput.WriteLine("adb shell logcat -b main -v raw -s Command:I"); //Listening for Info Logs titled "Command"
    
       while (true) { }
    }
    

    To flush logcat or send any command from the PC through ADB, I open another process and send the commands from there.

    Edit: You might want to add System.Threading.Thread.Sleep(2000); //pause for 2 seconds after each commands sent from the PC through ADB otherwise the device sometimes doesn't execute all commands when sent successively too quickly