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);// 查找环境变量中的adbvar 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;}}
}
应用示例:
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
:进程退出码。