是否有办法知道由 C# System.Diagnostics.Process 管理的 adb 命令何时完成?

问题描述 投票:0回答:1

我需要更改大量 Android 图片的日期,最简单的方法似乎是使用

adb shell
touch
命令。我不知道为什么,但
adb shell touch ...
不起作用,它说“只读文件系统”。但是,如果我运行
adb shell
,然后在该过程中继续运行
touch
,这是可能的。

我已经写过类似的东西了

var adb = Process.Start(new ProcessStartInfo("adb", "shell")
{
    RedirectStandardInput = true,
    RedirectStandardOutput = true,
    UseShellExecute = false,
    CreateNoWindow = true,
});
ArgumentNullException.ThrowIfNull(adb);

var outputTask = Task.Run(async () =>
{
    while (!adb.StandardOutput.EndOfStream)
    {
        var line = await adb.StandardOutput.ReadLineAsync();
        Console.WriteLine(line);
    }
});

adb.StandardInput.WriteLine("ls");
adb.StandardInput.WriteLine("cd sdcard/DCIM/Camera");
adb.StandardInput.WriteLine("touch -d \"2011-01-01 00:00:00\" receipt_660cb153bd075.jpg");
adb.StandardInput.WriteLine("stat receipt_660cb153bd075.jpg");

问题是,由于 C#

ls
实例在技术上尚未完成,我如何知道
Process
输出何时完成?

c# android shell process adb
1个回答
0
投票

我不确定这是最好的解决方案,但现在我附加一个

echo <something unique to my app>
来表示命令结束,然后我不断读取输出,直到到达该信号

// Usage:
using var reader = new ShellOutputReader(adb.StandardOutput.BaseStream);

adb.StandardInput.WriteLine("cd sdcard/DCIM/Camera");

var lsOutputTask = reader.ReadUntilCompleteAsync();
// Append the signal at the end of the command
adb.StandardInput.WriteLine($"ls;echo {ShellOutputReader.FinishToken}");
var lsOutput = await lsOutputTask;

// This should output the result of the `ls` command
Console.WriteLine(lsOutput);

// The reader
class ShellOutputReader : IDisposable
{
    public const string FinishToken = "COMMAND_FINISHED";

    CancellationTokenSource cts = new();
    TaskCompletionSource<string> tcs = new();
    readonly StringBuilder curr = new();
    readonly StreamReader reader;

    public ShellOutputReader(Stream stream)
    {
        reader = new(stream);

        var token = cts.Token;
        Task.Run(async () =>
        {
            while (!token.IsCancellationRequested)
            {
                var line = await reader.ReadLineAsync();

                if (line == FinishToken)
                {
                    tcs.SetResult(curr.ToString());
                    tcs = new();
                }
                else
                {
                    curr.AppendLine(line);
                }
            }
        });
    }

    public async Task<string> ReadUntilCompleteAsync()
    {
        return await tcs.Task;
    }

    public void Dispose()
    {
        reader.Dispose();
        cts.Cancel();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.