我需要更改大量 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
输出何时完成?
我不确定这是最好的解决方案,但现在我附加一个
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();
}
}