csharp
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ADB_Demo
{
/// <summary>
/// ADB管理器,提供与Android设备的通信功能
/// </summary>
public class AdbManager : IDisposable
{
private readonly string _adbPath;
private readonly Dictionary<string, Process> _runningProcesses = new();
private readonly object _processLock = new();
private bool _disposed;
/// <summary>
/// ADB管理器构造函数
/// </summary>
/// <param name="adbPath">ADB可执行文件路径,默认自动查找</param>
public AdbManager(string adbPath = null)
{
_adbPath = FindAdbPath(adbPath);
if (string.IsNullOrEmpty(_adbPath))
throw new FileNotFoundException("ADB executable not found");
}
private string FindAdbPath(string customPath)
{
if (!string.IsNullOrEmpty(customPath) && File.Exists(customPath))
return Path.GetFullPath(customPath);
// 查找环境变量中的adb
var paths = Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator) ?? Array.Empty<string>();
foreach (var path in paths)
{
try
{
var fullPath = Path.Combine(path, "adb.exe");
if (File.Exists(fullPath))
return fullPath;
}
catch
{
// 忽略无效路径
}
}
// 尝试Android SDK默认位置
var sdkPaths = new[]
{
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Android", "android-sdk", "platform-tools", "adb.exe"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "Local", "Android", "Sdk", "platform-tools", "adb.exe")
};
return sdkPaths.FirstOrDefault(File.Exists);
}
/// <summary>
/// 执行ADB命令并返回结果
/// </summary>
public async Task<AdbCommandResult> ExecuteCommandAsync(
string command,
CancellationToken cancellationToken = default,
int timeoutMilliseconds = 30000)
{
if (_disposed)
throw new ObjectDisposedException(nameof(AdbManager));
var processInfo = new ProcessStartInfo
{
FileName = _adbPath,
Arguments = command,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = System.Text.Encoding.UTF8,
StandardErrorEncoding = System.Text.Encoding.UTF8
};
var process = new Process { StartInfo = processInfo };
var processId = Guid.NewGuid().ToString();
lock (_processLock)
{
_runningProcesses.Add(processId, process);
}
try
{
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
var outputBuilder = new System.Text.StringBuilder();
var errorBuilder = new System.Text.StringBuilder();
process.OutputDataReceived += (_, e) => { if (e.Data != null) outputBuilder.AppendLine(e.Data); };
process.ErrorDataReceived += (_, e) => { if (e.Data != null) errorBuilder.AppendLine(e.Data); };
// 等待进程退出或超时
var processTask = Task.Run(() => process.WaitForExit(), cancellationToken);
var completedTask = await Task.WhenAny(processTask, Task.Delay(timeoutMilliseconds, cancellationToken));
if (completedTask != processTask)
{
throw new TimeoutException($"ADB command timed out after {timeoutMilliseconds}ms");
}
if (process.ExitCode != 0)
{
throw new AdbCommandException($"ADB command failed with exit code {process.ExitCode}",
errorBuilder.ToString(), process.ExitCode);
}
return new AdbCommandResult(outputBuilder.ToString().Trim(), errorBuilder.ToString().Trim());
}
finally
{
lock (_processLock)
{
_runningProcesses.Remove(processId);
}
if (!process.HasExited)
{
process.Kill();
}
process.Dispose();
}
}
/// <summary>
/// 获取连接的设备列表
/// </summary>
public async Task<List<AdbDevice>> GetDevicesAsync(CancellationToken cancellationToken = default)
{
var result = await ExecuteCommandAsync("devices -l", cancellationToken);
var lines = result.Output.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
// 跳过第一行标题行
return lines.Skip(1)
.Select(line => line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
.Where(parts => parts.Length >= 2)
.Select(parts => new AdbDevice
{
SerialNumber = parts[0],
Status = parts[1],
Properties = parts.Skip(2)
.Select(p => p.Split(':'))
.Where(p => p.Length == 2)
.ToDictionary(p => p[0], p => p[1])
})
.ToList();
}
/// <summary>
/// 停止所有正在运行的ADB进程
/// </summary>
public void StopAllProcesses()
{
lock (_processLock)
{
foreach (var process in _runningProcesses.Values)
{
try
{
if (!process.HasExited)
{
process.Kill();
}
}
catch
{
// 忽略停止过程中的错误
}
}
_runningProcesses.Clear();
}
}
public void Dispose()
{
if (_disposed) return;
StopAllProcesses();
_disposed = true;
GC.SuppressFinalize(this);
}
~AdbManager()
{
Dispose();
}
}
/// <summary>
/// ADB命令执行结果
/// </summary>
public class AdbCommandResult
{
public string Output { get; }
public string Error { get; }
public AdbCommandResult(string output, string error)
{
Output = output;
Error = error;
}
}
/// <summary>
/// ADB设备信息
/// </summary>
public class AdbDevice
{
public string SerialNumber { get; set; }
public string Status { get; set; }
public Dictionary<string, string> Properties { get; set; } = new();
public override string ToString() => $"{SerialNumber} ({Status})";
}
/// <summary>
/// ADB命令异常
/// </summary>
public class AdbCommandException : Exception
{
public string ErrorOutput { get; }
public int ExitCode { get; }
public AdbCommandException(string message, string errorOutput, int exitCode)
: base(message)
{
ErrorOutput = errorOutput;
ExitCode = exitCode;
}
}
}
应用示例:
csharp
namespace ADB_Demo
{
internal class Program
{
static async Task Main(string[] args)
{
using var adb = new AdbManager();
var ret = await adb.ExecuteCommandAsync("version");
// 1. 获取设备列表
var devices = await adb.GetDevicesAsync();
Console.WriteLine("Connected devices:");
foreach (var device in devices)
{
Console.WriteLine($"- {device.SerialNumber} ({device.Status})");
}
}
}
}
各函数的功能说明:
AdbManager 类
1. 构造函数 AdbManager(string adbPath = null)
• 功能 :初始化 ADB 管理器,自动查找或使用指定的 ADB 可执行文件路径。
• 参数 :
• adbPath
:可选,自定义 ADB 路径。若未提供,则自动搜索。
2. FindAdbPath(string customPath)
(私有方法)
• 功能 :查找 ADB 可执行文件的完整路径。
• 查找顺序:
- 优先使用
customPath
(如果有效)。 - 搜索系统
PATH
环境变量。 - 检查 Android SDK 默认安装路径(Windows 平台)。
3. ExecuteCommandAsync(string command, CancellationToken cancellationToken = default, int timeoutMilliseconds = 30000)
• 功能 :异步执行指定的 ADB 命令,并返回输出结果。
• 参数 :
• command
:要执行的 ADB 命令(如 "devices -l"
)。
• cancellationToken
:支持取消操作。
• timeoutMilliseconds
:超时时间(默认 30 秒)。
• 返回值 :AdbCommandResult
,包含标准输出和错误输出。
4. GetDevicesAsync(CancellationToken cancellationToken = default)
• 功能 :获取当前连接的 Android 设备列表。
• 实现 :调用 adb devices -l
并解析输出。
• 返回值 :List<AdbDevice>
,包含设备序列号、状态和属性(如 model
)。
5. StopAllProcesses()
• 功能 :强制终止所有正在运行的 ADB 进程。
• 用途:通常在释放资源时调用。
6. Dispose()
和析构函数 ~AdbManager()
• 功能 :实现 IDisposable
接口,清理资源(停止所有进程)。
辅助类
1. AdbCommandResult
• 功能 :封装 ADB 命令的执行结果。
• 属性 :
• Output
:标准输出内容。
• Error
:错误输出内容。
2. AdbDevice
• 功能 :表示一个连接的 Android 设备。
• 属性 :
• SerialNumber
:设备序列号(如 emulator-5554
)。
• Status
:设备状态(如 device
/offline
)。
• Properties
:设备属性字典(如 model:Android_SDK_built_for_x86
)。
3. AdbCommandException
• 功能 :自定义异常,表示 ADB 命令执行失败。
• 属性 :
• ErrorOutput
:错误输出内容。
• ExitCode
:进程退出码。