Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/200.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中等待ADB输出?_C#_Android_Windows_Command Line_Adb - Fatal编程技术网

如何在C#中等待ADB输出?

如何在C#中等待ADB输出?,c#,android,windows,command-line,adb,C#,Android,Windows,Command Line,Adb,我想使用ADB命令通过C程序从连接在USB中的设备接收信息,然后刷新输出 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

我想使用
ADB
命令通过C程序从连接在
USB
中的
设备
接收信息,然后刷新输出

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();

但这在C#中可行吗?
而且输出似乎没有刷新

这就是我过去为这些东西编写代码的方式 这是我的代码,希望你能理解

  //to run the all the cmd,adb.fastboot.exe command using these function
   //here in startfunc pass the .exe file u want to execute,Arguments which u want to pass 
    //string msg = It is nothing Extra message if u want to add to your final output


    private static string Execute(string Startfunc, String Arguments,string msg)
    {   
        string text = null;
        Process p = new Process();
        p.StartInfo.FileName = Startfunc;
        p.StartInfo.Arguments = Arguments;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardOutput = true;         
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.EnableRaisingEvents = true;
        p.Start(); 
        do
        {
            Application.DoEvents();
            string output = p.StandardOutput.ReadToEnd();
            text += output;
            string err = p.StandardError.ReadToEnd();
            text += err;
        }
        while (!p.HasExited);
        text += msg;
        return text;
    }

     //now i will call above function and make it wait until we get the result

     private void normal_reboot_Click(object sender, EventArgs e)
    { 
        
            txt_Log.Text = "rebooting" +Environment.NewLine;
            Task t = Task.Factory.StartNew(() =>
            {
                txt_Log.Text=Execute("adb.exe","reboot","Done");
            });
            do { Application.DoEvents(); } while (!t.IsCompleted);                                    
    }

你不能一次读到最后
ReadToEnd
的最终意思是“直到管道关闭,我已经消耗了所有的数据,再也不会有数据到达”
ReadToEnd
也将永远不会完成,直到
adb.exe
故意发出它已完成写入(并且永远不会再写入)的信号,或者终止—所以这就是为什么您没有达到刷新的程度


你可以做的是读取(如果需要的话,一次读取一个字节/字符),直到你有,比如说,一行——所以如果这里的期望是“一个命令输入,一行输出”,那么它就足够简单了。如果没有办法知道有多少行将返回,那么您通常会使用两个线程,并有一个专用的读卡器线程,该线程从
进程获取数据。StandardOutput
(一次一个字节/字符,或一行一行)并执行所需的任何操作。

您还可以异步查找输出/错误消息。因此,您不需要(阻塞)循环: 此示例仅输出消息,但可以通过完整方法进行扩展

p.OutputDataReceived+= (s, e) => Console.WriteLine(e.Data);
p.BeginOutputReadLine();//This is important, otherwise the event won't be fired
p.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
p.BeginErrorReadLine();

这应该打印下面adb收到的每一行工作代码,我们不直接调用adb.exe,而是通过
cmd.exe
,命令等待来自logcat的任何信息日志,标题为“command”:
adb shell logcat-b main-v raw-s命令: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) { }
}
要刷新logcat或通过ADB从PC发送任何命令,我打开另一个进程并从那里发送命令

编辑:
您可能需要添加
System.Threading.Thread.Sleep(2000)//在通过ADB从PC发送每个命令后,暂停2秒,否则设备有时在连续发送的命令过快时无法执行所有命令。。。不要认为这段代码按照你认为的方式工作;在
do
/
循环中使用
ReadToEnd
没有意义;我认为这段代码主要是偶然运行的(如果应用程序关闭了
stdout
stderr
但仍在运行,那么它看起来会创建一个热循环)期望的只是监听,直到设备发出一条线路。我接受了你的建议,先用ReadLine()修改ReadToEnd(),然后用Read()修改了ReadToEnd(),但在这两种情况下似乎都没有达到预期效果flushing@JosB那么,
logcat
是否返回过空行?因为空行是
do
循环退出的唯一方式。请注意,EOF与空行不同,如果输出在换行后终止,我希望从最终的
ReadToEnd
接收
null
,因此:您可能需要注意这一点。最后,为了调试它,我将在某处编写来自
adb
的输出,包括使
null
变得明显;它曾经停止过吗?它是否返回一个空行?它是否返回
null
?我不知道,但这些是你应该检查的东西
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) { }
}