C# ADB 安卓设备数据传输工具

C# ADB工具,支持文件传输、APK安装、截图、日志抓取、Shell命令执行等功能。

一、项目结构

复制代码
AdbTool/
├── AdbTool.csproj
├── Program.cs
├── MainForm.cs
├── MainForm.Designer.cs
├── Adb/
│   ├── AdbManager.cs          ★ 核心ADB管理
│   ├── DeviceInfo.cs          设备信息模型
│   ├── FileTransfer.cs        文件传输
│   ├── AppManager.cs          APK管理
│   ├── ScreenCapture.cs       截图工具
│   └── LogCat.cs              日志抓取
├── Utils/
│   ├── ProcessExecutor.cs     进程执行
│   ├── AdbCommandBuilder.cs   ADB命令构建
│   └── ProgressReporter.cs    进度报告
└── Models/
    ├── Device.cs
    ├── FileEntry.cs
    └── TransferProgress.cs

二、核心代码实现

1. 主程序入口 (Program.cs)

csharp 复制代码
using System;
using System.Windows.Forms;

namespace AdbTool
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            
            // 检查ADB环境
            if (!AdbManager.CheckAdbAvailable())
            {
                MessageBox.Show("未找到ADB工具!\n请确保已安装Android SDK Platform-Tools,并已添加到PATH环境变量。", 
                    "环境检查", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            
            Application.Run(new MainForm());
        }
    }
}

2. 主窗体 (MainForm.cs)

csharp 复制代码
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using AdbTool.Adb;
using AdbTool.Models;

namespace AdbTool
{
    public partial class MainForm : Form
    {
        private AdbManager adbManager;
        private DeviceInfo selectedDevice;
        
        public MainForm()
        {
            InitializeComponent();
            InitializeAdb();
        }
        
        private void InitializeComponent()
        {
            this.Text = "ADB 安卓设备管理工具";
            this.Size = new Size(1000, 700);
            this.StartPosition = FormStartPosition.CenterScreen;
            
            // 创建设备列表组
            GroupBox gbDevices = new GroupBox
            {
                Text = "已连接设备",
                Location = new Point(10, 10),
                Size = new Size(300, 150)
            };
            
            lstDevices = new ListView
            {
                Location = new Point(10, 25),
                Size = new Size(280, 100),
                View = View.Details,
                FullRowSelect = true,
                GridLines = true
            };
            lstDevices.Columns.Add("设备序列号", 120);
            lstDevices.Columns.Add("设备型号", 80);
            lstDevices.Columns.Add("Android版本", 70);
            lstDevices.SelectedIndexChanged += LstDevices_SelectedIndexChanged;
            
            btnRefreshDevices = new Button
            {
                Text = "刷新设备",
                Location = new Point(10, 130),
                Size = new Size(80, 25)
            };
            btnRefreshDevices.Click += BtnRefreshDevices_Click;
            
            gbDevices.Controls.Add(lstDevices);
            gbDevices.Controls.Add(btnRefreshDevices);
            
            // 设备信息组
            GroupBox gbDeviceInfo = new GroupBox
            {
                Text = "设备信息",
                Location = new Point(10, 170),
                Size = new Size(300, 200)
            };
            
            lblDeviceDetails = new Label
            {
                Location = new Point(10, 25),
                Size = new Size(280, 160),
                Text = "请选择一个设备..."
            };
            
            gbDeviceInfo.Controls.Add(lblDeviceDetails);
            
            // 功能选项卡
            TabControl tabControl = new TabControl
            {
                Location = new Point(320, 10),
                Size = new Size(650, 640)
            };
            
            // 文件管理标签页
            TabPage tabFiles = new TabPage("文件管理");
            InitializeFileTab(tabFiles);
            
            // APK管理标签页
            TabPage tabApps = new TabPage("APK管理");
            InitializeAppTab(tabApps);
            
            // 截图标签页
            TabPage tabScreenshot = new TabPage("截图");
            InitializeScreenshotTab(tabScreenshot);
            
            // 日志标签页
            TabPage tabLogs = new TabPage("日志");
            InitializeLogTab(tabLogs);
            
            // Shell命令标签页
            TabPage tabShell = new TabPage("Shell命令");
            InitializeShellTab(tabShell);
            
            tabControl.TabPages.AddRange(new TabPage[] { tabFiles, tabApps, tabScreenshot, tabLogs, tabShell });
            
            // 状态栏
            statusStrip = new StatusStrip();
            statusLabel = new ToolStripStatusLabel("就绪");
            statusStrip.Items.Add(statusLabel);
            
            this.Controls.AddRange(new Control[] { gbDevices, gbDeviceInfo, tabControl, statusStrip });
        }
        
        private void InitializeFileTab(TabPage tab)
        {
            // 文件路径显示
            Label lblLocalPath = new Label
            {
                Text = "本地路径:",
                Location = new Point(10, 10),
                Size = new Size(60, 20)
            };
            
            txtLocalPath = new TextBox
            {
                Location = new Point(70, 8),
                Size = new Size(300, 20),
                ReadOnly = true
            };
            
            btnBrowseLocal = new Button
            {
                Text = "浏览...",
                Location = new Point(380, 6),
                Size = new Size(70, 25)
            };
            btnBrowseLocal.Click += BtnBrowseLocal_Click;
            
            Label lblRemotePath = new Label
            {
                Text = "设备路径:",
                Location = new Point(10, 40),
                Size = new Size(60, 20)
            };
            
            txtRemotePath = new TextBox
            {
                Text = "/sdcard/",
                Location = new Point(70, 38),
                Size = new Size(300, 20)
            };
            
            // 文件列表
            lstLocalFiles = new ListView
            {
                Location = new Point(10, 70),
                Size = new Size(310, 200),
                View = View.List
            };
            
            lstRemoteFiles = new ListView
            {
                Location = new Point(330, 70),
                Size = new Size(310, 200),
                View = View.List
            };
            
            // 传输按钮
            btnPush = new Button
            {
                Text = "推送到设备 →",
                Location = new Point(120, 280),
                Size = new Size(100, 30),
                BackColor = Color.LightGreen
            };
            btnPush.Click += BtnPush_Click;
            
            btnPull = new Button
            {
                Text = "← 拉取到本地",
                Location = new Point(230, 280),
                Size = new Size(100, 30),
                BackColor = Color.LightBlue
            };
            btnPull.Click += BtnPull_Click;
            
            // 进度条
            progressBar = new ProgressBar
            {
                Location = new Point(10, 320),
                Size = new Size(630, 20)
            };
            
            lblProgress = new Label
            {
                Location = new Point(10, 350),
                Size = new Size(630, 20),
                Text = "就绪"
            };
            
            tab.Controls.AddRange(new Control[] {
                lblLocalPath, txtLocalPath, btnBrowseLocal,
                lblRemotePath, txtRemotePath,
                lstLocalFiles, lstRemoteFiles,
                btnPush, btnPull,
                progressBar, lblProgress
            });
        }
        
        private void InitializeAppTab(TabPage tab)
        {
            // APK列表
            lstInstalledApps = new ListView
            {
                Location = new Point(10, 10),
                Size = new Size(400, 300),
                View = View.Details,
                FullRowSelect = true,
                GridLines = true
            };
            lstInstalledApps.Columns.Add("包名", 200);
            lstInstalledApps.Columns.Add("版本", 100);
            lstInstalledApps.Columns.Add("路径", 150);
            
            // APK操作按钮
            btnInstallApk = new Button
            {
                Text = "安装APK",
                Location = new Point(10, 320),
                Size = new Size(80, 30)
            };
            btnInstallApk.Click += BtnInstallApk_Click;
            
            btnUninstallApp = new Button
            {
                Text = "卸载应用",
                Location = new Point(100, 320),
                Size = new Size(80, 30)
            };
            btnUninstallApp.Click += BtnUninstallApp_Click;
            
            btnLaunchApp = new Button
            {
                Text = "启动应用",
                Location = new Point(190, 320),
                Size = new Size(80, 30)
            };
            btnLaunchApp.Click += BtnLaunchApp_Click;
            
            btnClearAppData = new Button
            {
                Text = "清除数据",
                Location = new Point(280, 320),
                Size = new Size(80, 30)
            };
            btnClearAppData.Click += BtnClearAppData_Click;
            
            tab.Controls.AddRange(new Control[] {
                lstInstalledApps,
                btnInstallApk, btnUninstallApp, btnLaunchApp, btnClearAppData
            });
        }
        
        private void InitializeScreenshotTab(TabPage tab)
        {
            pictureBox = new PictureBox
            {
                Location = new Point(10, 10),
                Size = new Size(400, 300),
                BorderStyle = BorderStyle.FixedSingle,
                SizeMode = PictureBoxSizeMode.Zoom
            };
            
            btnTakeScreenshot = new Button
            {
                Text = "截取屏幕",
                Location = new Point(10, 320),
                Size = new Size(100, 30)
            };
            btnTakeScreenshot.Click += BtnTakeScreenshot_Click;
            
            btnSaveScreenshot = new Button
            {
                Text = "保存截图",
                Location = new Point(120, 320),
                Size = new Size(100, 30)
            };
            btnSaveScreenshot.Click += BtnSaveScreenshot_Click;
            
            tab.Controls.AddRange(new Control[] { pictureBox, btnTakeScreenshot, btnSaveScreenshot });
        }
        
        private void InitializeLogTab(TabPage tab)
        {
            txtLog = new RichTextBox
            {
                Location = new Point(10, 10),
                Size = new Size(630, 350),
                ReadOnly = true,
                Font = new Font("Consolas", 9),
                BackColor = Color.Black,
                ForeColor = Color.LightGreen
            };
            
            btnStartLog = new Button
            {
                Text = "开始抓日志",
                Location = new Point(10, 370),
                Size = new Size(100, 30)
            };
            btnStartLog.Click += BtnStartLog_Click;
            
            btnStopLog = new Button
            {
                Text = "停止抓日志",
                Location = new Point(120, 370),
                Size = new Size(100, 30)
            };
            btnStopLog.Click += BtnStopLog_Click;
            
            btnClearLog = new Button
            {
                Text = "清空日志",
                Location = new Point(230, 370),
                Size = new Size(100, 30)
            };
            btnClearLog.Click += BtnClearLog_Click;
            
            tab.Controls.AddRange(new Control[] { txtLog, btnStartLog, btnStopLog, btnClearLog });
        }
        
        private void InitializeShellTab(TabPage tab)
        {
            txtShellOutput = new RichTextBox
            {
                Location = new Point(10, 10),
                Size = new Size(630, 300),
                ReadOnly = true,
                Font = new Font("Consolas", 9),
                BackColor = Color.Black,
                ForeColor = Color.White
            };
            
            txtShellCommand = new TextBox
            {
                Location = new Point(10, 320),
                Size = new Size(530, 25)
            };
            txtShellCommand.KeyDown += TxtShellCommand_KeyDown;
            
            btnExecuteShell = new Button
            {
                Text = "执行",
                Location = new Point(550, 318),
                Size = new Size(80, 27)
            };
            btnExecuteShell.Click += BtnExecuteShell_Click;
            
            tab.Controls.AddRange(new Control[] { txtShellOutput, txtShellCommand, btnExecuteShell });
        }
        
        private void InitializeAdb()
        {
            adbManager = new AdbManager();
            RefreshDeviceList();
        }
        
        #region 事件处理
        
        private void BtnRefreshDevices_Click(object sender, EventArgs e)
        {
            RefreshDeviceList();
        }
        
        private void LstDevices_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstDevices.SelectedItems.Count > 0)
            {
                string serial = lstDevices.SelectedItems[0].Text;
                selectedDevice = adbManager.GetDeviceBySerial(serial);
                UpdateDeviceInfo();
                RefreshFileLists();
                RefreshAppList();
            }
        }
        
        private void BtnBrowseLocal_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog dialog = new FolderBrowserDialog())
            {
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    txtLocalPath.Text = dialog.SelectedPath;
                    RefreshLocalFileList();
                }
            }
        }
        
        private void BtnPush_Click(object sender, EventArgs e)
        {
            if (selectedDevice == null)
            {
                MessageBox.Show("请先选择设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            if (lstLocalFiles.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择要推送的文件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            string localFile = Path.Combine(txtLocalPath.Text, lstLocalFiles.SelectedItems[0].Text);
            string remotePath = txtRemotePath.Text;
            
            adbManager.PushFile(selectedDevice.Serial, localFile, remotePath, 
                (progress) => 
                {
                    progressBar.Value = progress.Percentage;
                    lblProgress.Text = $"推送中... {progress.Percentage}%";
                },
                () =>
                {
                    lblProgress.Text = "推送完成!";
                    RefreshRemoteFileList();
                },
                (error) =>
                {
                    lblProgress.Text = $"推送失败: {error}";
                });
        }
        
        private void BtnPull_Click(object sender, EventArgs e)
        {
            if (selectedDevice == null)
            {
                MessageBox.Show("请先选择设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            if (lstRemoteFiles.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择要拉取的文件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            string remoteFile = txtRemotePath.Text + "/" + lstRemoteFiles.SelectedItems[0].Text;
            string localPath = txtLocalPath.Text;
            
            adbManager.PullFile(selectedDevice.Serial, remoteFile, localPath,
                (progress) =>
                {
                    progressBar.Value = progress.Percentage;
                    lblProgress.Text = $"拉取中... {progress.Percentage}%";
                },
                () =>
                {
                    lblProgress.Text = "拉取完成!";
                    RefreshLocalFileList();
                },
                (error) =>
                {
                    lblProgress.Text = $"拉取失败: {error}";
                });
        }
        
        private void BtnInstallApk_Click(object sender, EventArgs e)
        {
            if (selectedDevice == null)
            {
                MessageBox.Show("请先选择设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            using (OpenFileDialog dialog = new OpenFileDialog())
            {
                dialog.Filter = "APK文件|*.apk";
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    adbManager.InstallApk(selectedDevice.Serial, dialog.FileName,
                        (msg) => UpdateStatus(msg),
                        () => UpdateStatus("APK安装完成!"),
                        (error) => UpdateStatus($"安装失败: {error}"));
                }
            }
        }
        
        private void BtnUninstallApp_Click(object sender, EventArgs e)
        {
            if (selectedDevice == null || lstInstalledApps.SelectedItems.Count == 0)
                return;
            
            string packageName = lstInstalledApps.SelectedItems[0].Text;
            adbManager.UninstallApp(selectedDevice.Serial, packageName,
                (msg) => UpdateStatus(msg),
                () => 
                {
                    UpdateStatus("应用卸载完成!");
                    RefreshAppList();
                },
                (error) => UpdateStatus($"卸载失败: {error}"));
        }
        
        private void BtnTakeScreenshot_Click(object sender, EventArgs e)
        {
            if (selectedDevice == null)
            {
                MessageBox.Show("请先选择设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            string screenshotPath = Path.Combine(Path.GetTempPath(), "screenshot.png");
            adbManager.TakeScreenshot(selectedDevice.Serial, screenshotPath,
                (msg) => UpdateStatus(msg),
                () =>
                {
                    UpdateStatus("截图完成!");
                    if (File.Exists(screenshotPath))
                    {
                        pictureBox.Image = Image.FromFile(screenshotPath);
                    }
                },
                (error) => UpdateStatus($"截图失败: {error}"));
        }
        
        private void BtnStartLog_Click(object sender, EventArgs e)
        {
            if (selectedDevice == null)
            {
                MessageBox.Show("请先选择设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            adbManager.StartLogCat(selectedDevice.Serial, (log) =>
            {
                txtLog.Invoke(new Action(() =>
                {
                    txtLog.AppendText(log + "\n");
                    txtLog.ScrollToCaret();
                }));
            });
            UpdateStatus("开始抓取日志...");
        }
        
        private void BtnStopLog_Click(object sender, EventArgs e)
        {
            adbManager.StopLogCat();
            UpdateStatus("停止抓取日志");
        }
        
        private void BtnClearLog_Click(object sender, EventArgs e)
        {
            txtLog.Clear();
        }
        
        private void BtnExecuteShell_Click(object sender, EventArgs e)
        {
            if (selectedDevice == null)
            {
                MessageBox.Show("请先选择设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            
            string command = txtShellCommand.Text.Trim();
            if (string.IsNullOrEmpty(command))
                return;
            
            adbManager.ExecuteShellCommand(selectedDevice.Serial, command,
                (output) =>
                {
                    txtShellOutput.Invoke(new Action(() =>
                    {
                        txtShellOutput.AppendText(output + "\n");
                        txtShellOutput.ScrollToCaret();
                    }));
                },
                (error) =>
                {
                    txtShellOutput.Invoke(new Action(() =>
                    {
                        txtShellOutput.AppendText($"错误: {error}\n", Color.Red);
                    }));
                });
        }
        
        private void TxtShellCommand_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                BtnExecuteShell_Click(sender, EventArgs.Empty);
                txtShellCommand.Clear();
            }
        }
        
        #endregion
        
        #region 辅助方法
        
        private void RefreshDeviceList()
        {
            lstDevices.Items.Clear();
            var devices = adbManager.GetConnectedDevices();
            
            foreach (var device in devices)
            {
                var item = new ListViewItem(device.Serial);
                item.SubItems.Add(device.Model);
                item.SubItems.Add(device.AndroidVersion);
                lstDevices.Items.Add(item);
            }
            
            UpdateStatus($"发现 {devices.Count} 个设备");
        }
        
        private void UpdateDeviceInfo()
        {
            if (selectedDevice == null) return;
            
            string info = $"序列号: {selectedDevice.Serial}\n" +
                        $"型号: {selectedDevice.Model}\n" +
                        $"厂商: {selectedDevice.Manufacturer}\n" +
                        $"Android版本: {selectedDevice.AndroidVersion}\n" +
                        $"SDK版本: {selectedDevice.SdkVersion}\n" +
                        $"CPU架构: {selectedDevice.CpuAbi}\n" +
                        $"内存: {selectedDevice.Memory}\n" +
                        $"存储: {selectedDevice.Storage}";
            
            lblDeviceDetails.Text = info;
        }
        
        private void RefreshFileLists()
        {
            RefreshLocalFileList();
            RefreshRemoteFileList();
        }
        
        private void RefreshLocalFileList()
        {
            lstLocalFiles.Items.Clear();
            if (Directory.Exists(txtLocalPath.Text))
            {
                var files = Directory.GetFiles(txtLocalPath.Text);
                foreach (var file in files)
                {
                    lstLocalFiles.Items.Add(Path.GetFileName(file));
                }
            }
        }
        
        private void RefreshRemoteFileList()
        {
            if (selectedDevice == null) return;
            
            lstRemoteFiles.Items.Clear();
            var files = adbManager.ListFiles(selectedDevice.Serial, txtRemotePath.Text);
            foreach (var file in files)
            {
                lstRemoteFiles.Items.Add(file);
            }
        }
        
        private void RefreshAppList()
        {
            if (selectedDevice == null) return;
            
            lstInstalledApps.Items.Clear();
            var apps = adbManager.GetInstalledApps(selectedDevice.Serial);
            foreach (var app in apps)
            {
                var item = new ListViewItem(app.PackageName);
                item.SubItems.Add(app.Version);
                item.SubItems.Add(app.Path);
                lstInstalledApps.Items.Add(item);
            }
        }
        
        private void UpdateStatus(string message)
        {
            if (statusStrip.InvokeRequired)
            {
                statusStrip.Invoke(new Action<string>(UpdateStatus), message);
                return;
            }
            statusLabel.Text = message;
        }
        
        #endregion
        
        // 控件声明
        private ListView lstDevices;
        private Button btnRefreshDevices;
        private Label lblDeviceDetails;
        private TextBox txtLocalPath;
        private Button btnBrowseLocal;
        private TextBox txtRemotePath;
        private ListView lstLocalFiles;
        private ListView lstRemoteFiles;
        private Button btnPush;
        private Button btnPull;
        private ProgressBar progressBar;
        private Label lblProgress;
        private ListView lstInstalledApps;
        private Button btnInstallApk;
        private Button btnUninstallApp;
        private Button btnLaunchApp;
        private Button btnClearAppData;
        private PictureBox pictureBox;
        private Button btnTakeScreenshot;
        private Button btnSaveScreenshot;
        private RichTextBox txtLog;
        private Button btnStartLog;
        private Button btnStopLog;
        private Button btnClearLog;
        private RichTextBox txtShellOutput;
        private TextBox txtShellCommand;
        private Button btnExecuteShell;
        private StatusStrip statusStrip;
        private ToolStripStatusLabel statusLabel;
    }
}

3. ADB 管理器核心类 (AdbManager.cs)

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using AdbTool.Models;
using AdbTool.Utils;

namespace AdbTool.Adb
{
    public class AdbManager
    {
        private ProcessExecutor processExecutor;
        private string adbPath = "adb";
        
        public AdbManager()
        {
            processExecutor = new ProcessExecutor();
            FindAdbPath();
        }
        
        private void FindAdbPath()
        {
            // 尝试从环境变量查找adb
            string path = Environment.GetEnvironmentVariable("PATH");
            if (path != null)
            {
                string[] paths = path.Split(Path.PathSeparator);
                foreach (string p in paths)
                {
                    string adb = Path.Combine(p, "adb.exe");
                    if (File.Exists(adb))
                    {
                        adbPath = adb;
                        return;
                    }
                }
            }
            
            // 常见安装路径
            string[] commonPaths =
            {
                @"C:\Android\platform-tools\adb.exe",
                @"C:\Program Files\Android\platform-tools\adb.exe",
                @"C:\Users\" + Environment.UserName + @"\AppData\Local\Android\platform-tools\adb.exe"
            };
            
            foreach (string p in commonPaths)
            {
                if (File.Exists(p))
                {
                    adbPath = p;
                    return;
                }
            }
        }
        
        public static bool CheckAdbAvailable()
        {
            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = "adb",
                    Arguments = "version",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    CreateNoWindow = true
                };
                
                Process process = Process.Start(psi);
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                
                return output.Contains("Android Debug Bridge");
            }
            catch
            {
                return false;
            }
        }
        
        public List<DeviceInfo> GetConnectedDevices()
        {
            var devices = new List<DeviceInfo>();
            string output = ExecuteAdbCommand("devices -l");
            
            string[] lines = output.Split('\n');
            foreach (string line in lines)
            {
                if (line.Contains("\tdevice") && !line.Contains("List of devices attached"))
                {
                    string serial = line.Split('\t')[0].Trim();
                    var device = new DeviceInfo { Serial = serial };
                    
                    // 获取设备详细信息
                    string props = ExecuteAdbCommand($"-s {serial} shell getprop");
                    device.Model = ExtractProperty(props, "ro.product.model");
                    device.Manufacturer = ExtractProperty(props, "ro.product.manufacturer");
                    device.AndroidVersion = ExtractProperty(props, "ro.build.version.release");
                    device.SdkVersion = ExtractProperty(props, "ro.build.version.sdk");
                    device.CpuAbi = ExtractProperty(props, "ro.product.cpu.abi");
                    device.Memory = ExtractProperty(props, "memtotal");
                    device.Storage = ExtractProperty(props, "storagetotal");
                    
                    devices.Add(device);
                }
            }
            
            return devices;
        }
        
        public DeviceInfo GetDeviceBySerial(string serial)
        {
            var devices = GetConnectedDevices();
            return devices.Find(d => d.Serial == serial);
        }
        
        #region 文件操作
        
        public void PushFile(string serial, string localPath, string remotePath, 
            Action<TransferProgress> progressCallback = null,
            Action completedCallback = null,
            Action<string> errorCallback = null)
        {
            try
            {
                string fileName = Path.GetFileName(localPath);
                string fullRemotePath = remotePath.EndsWith("/") ? remotePath + fileName : remotePath + "/" + fileName;
                
                // 使用adb push命令
                ExecuteAdbCommandAsync($"-s {serial} push \"{localPath}\" \"{fullRemotePath}\"",
                    (output) =>
                    {
                        // 解析进度
                        if (progressCallback != null)
                        {
                            var progress = ParseTransferProgress(output);
                            progressCallback(progress);
                        }
                    },
                    () => completedCallback?.Invoke(),
                    (error) => errorCallback?.Invoke(error));
            }
            catch (Exception ex)
            {
                errorCallback?.Invoke(ex.Message);
            }
        }
        
        public void PullFile(string serial, string remotePath, string localPath,
            Action<TransferProgress> progressCallback = null,
            Action completedCallback = null,
            Action<string> errorCallback = null)
        {
            try
            {
                string fileName = Path.GetFileName(remotePath);
                string fullLocalPath = Path.Combine(localPath, fileName);
                
                ExecuteAdbCommandAsync($"-s {serial} pull \"{remotePath}\" \"{fullLocalPath}\"",
                    (output) =>
                    {
                        if (progressCallback != null)
                        {
                            var progress = ParseTransferProgress(output);
                            progressCallback(progress);
                        }
                    },
                    () => completedCallback?.Invoke(),
                    (error) => errorCallback?.Invoke(error));
            }
            catch (Exception ex)
            {
                errorCallback?.Invoke(ex.Message);
            }
        }
        
        public List<string> ListFiles(string serial, string remotePath)
        {
            var files = new List<string>();
            string output = ExecuteAdbCommand($"-s {serial} shell ls -la \"{remotePath}\"");
            
            string[] lines = output.Split('\n');
            foreach (string line in lines)
            {
                if (!string.IsNullOrWhiteSpace(line) && !line.Contains("total"))
                {
                    string[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length >= 8)
                    {
                        string fileName = parts[7];
                        if (fileName != "." && fileName != "..")
                        {
                            files.Add(fileName);
                        }
                    }
                }
            }
            
            return files;
        }
        
        #endregion
        
        #region APK管理
        
        public void InstallApk(string serial, string apkPath,
            Action<string> progressCallback = null,
            Action completedCallback = null,
            Action<string> errorCallback = null)
        {
            progressCallback?.Invoke("开始安装APK...");
            
            ExecuteAdbCommandAsync($"-s {serial} install -r \"{apkPath}\"",
                (output) => progressCallback?.Invoke(output),
                () => completedCallback?.Invoke(),
                (error) => errorCallback?.Invoke(error));
        }
        
        public void UninstallApp(string serial, string packageName,
            Action<string> progressCallback = null,
            Action completedCallback = null,
            Action<string> errorCallback = null)
        {
            progressCallback?.Invoke("开始卸载应用...");
            
            ExecuteAdbCommandAsync($"-s {serial} uninstall {packageName}",
                (output) => progressCallback?.Invoke(output),
                () => completedCallback?.Invoke(),
                (error) => errorCallback?.Invoke(error));
        }
        
        public List<AppInfo> GetInstalledApps(string serial)
        {
            var apps = new List<AppInfo>();
            string output = ExecuteAdbCommand($"-s {serial} shell pm list packages -f");
            
            string[] lines = output.Split('\n');
            foreach (string line in lines)
            {
                if (line.StartsWith("package:"))
                {
                    string[] parts = line.Substring(8).Split('=');
                    if (parts.Length == 2)
                    {
                        apps.Add(new AppInfo
                        {
                            Path = parts[0],
                            PackageName = parts[1]
                        });
                    }
                }
            }
            
            return apps;
        }
        
        #endregion
        
        #region 截图
        
        public void TakeScreenshot(string serial, string savePath,
            Action<string> progressCallback = null,
            Action completedCallback = null,
            Action<string> errorCallback = null)
        {
            try
            {
                progressCallback?.Invoke("正在截取屏幕...");
                
                // 截图到设备
                ExecuteAdbCommand($"-s {serial} shell screencap -p /sdcard/screenshot.png");
                
                progressCallback?.Invoke("正在拉取截图...");
                
                // 拉取到本地
                PullFile(serial, "/sdcard/screenshot.png", Path.GetDirectoryName(savePath),
                    null,
                    () =>
                    {
                        // 删除设备上的临时文件
                        ExecuteAdbCommand($"-s {serial} shell rm /sdcard/screenshot.png");
                        completedCallback?.Invoke();
                    },
                    (error) => errorCallback?.Invoke(error));
            }
            catch (Exception ex)
            {
                errorCallback?.Invoke(ex.Message);
            }
        }
        
        #endregion
        
        #region 日志
        
        private Process logcatProcess;
        
        public void StartLogCat(string serial, Action<string> logCallback)
        {
            StopLogCat();
            
            logcatProcess = new Process();
            logcatProcess.StartInfo.FileName = adbPath;
            logcatProcess.StartInfo.Arguments = $"-s {serial} logcat -v time";
            logcatProcess.StartInfo.UseShellExecute = false;
            logcatProcess.StartInfo.RedirectStandardOutput = true;
            logcatProcess.StartInfo.CreateNoWindow = true;
            
            logcatProcess.OutputDataReceived += (sender, args) =>
            {
                if (!string.IsNullOrEmpty(args.Data))
                {
                    logCallback?.Invoke(args.Data);
                }
            };
            
            logcatProcess.Start();
            logcatProcess.BeginOutputReadLine();
        }
        
        public void StopLogCat()
        {
            if (logcatProcess != null && !logcatProcess.HasExited)
            {
                logcatProcess.Kill();
                logcatProcess.Dispose();
                logcatProcess = null;
            }
        }
        
        #endregion
        
        #region Shell命令
        
        public void ExecuteShellCommand(string serial, string command,
            Action<string> outputCallback = null,
            Action<string> errorCallback = null)
        {
            ExecuteAdbCommandAsync($"-s {serial} shell \"{command}\"",
                (output) => outputCallback?.Invoke(output),
                null,
                (error) => errorCallback?.Invoke(error));
        }
        
        #endregion
        
        #region 辅助方法
        
        private string ExecuteAdbCommand(string arguments)
        {
            return processExecutor.Execute(adbPath, arguments);
        }
        
        private void ExecuteAdbCommandAsync(string arguments,
            Action<string> outputCallback,
            Action completedCallback,
            Action<string> errorCallback)
        {
            processExecutor.ExecuteAsync(adbPath, arguments,
                outputCallback,
                completedCallback,
                errorCallback);
        }
        
        private string ExtractProperty(string props, string key)
        {
            string[] lines = props.Split('\n');
            foreach (string line in lines)
            {
                if (line.Contains(key))
                {
                    int colonIndex = line.IndexOf(':');
                    if (colonIndex >= 0)
                    {
                        return line.Substring(colonIndex + 1).Trim();
                    }
                }
            }
            return "Unknown";
        }
        
        private TransferProgress ParseTransferProgress(string output)
        {
            // 解析adb push/pull的输出格式
            // 例如: 100% /sdcard/file.txt
            var progress = new TransferProgress();
            
            if (output.Contains("%"))
            {
                int percentIndex = output.IndexOf('%');
                if (percentIndex > 0)
                {
                    string percentStr = output.Substring(percentIndex - 3, 3).Trim();
                    if (int.TryParse(percentStr, out int percent))
                    {
                        progress.Percentage = percent;
                    }
                }
            }
            
            progress.Status = output.Trim();
            return progress;
        }
        
        #endregion
    }
}

4. 设备信息模型 (DeviceInfo.cs)

csharp 复制代码
using System;

namespace AdbTool.Models
{
    public class DeviceInfo
    {
        public string Serial { get; set; }
        public string Model { get; set; }
        public string Manufacturer { get; set; }
        public string AndroidVersion { get; set; }
        public string SdkVersion { get; set; }
        public string CpuAbi { get; set; }
        public string Memory { get; set; }
        public string Storage { get; set; }
        public bool IsEmulator => Serial.Contains("emulator") || Serial.Contains("5554");
        
        public override string ToString()
        {
            return $"{Manufacturer} {Model} ({AndroidVersion}) - {Serial}";
        }
    }
    
    public class AppInfo
    {
        public string PackageName { get; set; }
        public string Version { get; set; }
        public string Path { get; set; }
    }
    
    public class TransferProgress
    {
        public int Percentage { get; set; }
        public string Status { get; set; }
        public long BytesTransferred { get; set; }
        public long TotalBytes { get; set; }
    }
}

5. 进程执行器 (ProcessExecutor.cs)

csharp 复制代码
using System;
using System.Diagnostics;
using System.Text;

namespace AdbTool.Utils
{
    public class ProcessExecutor
    {
        public string Execute(string fileName, string arguments)
        {
            try
            {
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = fileName,
                    Arguments = arguments,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true,
                    StandardOutputEncoding = Encoding.UTF8,
                    StandardErrorEncoding = Encoding.UTF8
                };
                
                Process process = Process.Start(psi);
                string output = process.StandardOutput.ReadToEnd();
                string error = process.StandardError.ReadToEnd();
                process.WaitForExit();
                
                return string.IsNullOrEmpty(error) ? output : error;
            }
            catch (Exception ex)
            {
                return $"执行失败: {ex.Message}";
            }
        }
        
        public void ExecuteAsync(string fileName, string arguments,
            Action<string> outputCallback,
            Action completedCallback,
            Action<string> errorCallback)
        {
            try
            {
                Process process = new Process();
                process.StartInfo.FileName = fileName;
                process.StartInfo.Arguments = arguments;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.CreateNoWindow = true;
                
                StringBuilder outputBuilder = new StringBuilder();
                
                process.OutputDataReceived += (sender, args) =>
                {
                    if (!string.IsNullOrEmpty(args.Data))
                    {
                        outputBuilder.AppendLine(args.Data);
                        outputCallback?.Invoke(args.Data);
                    }
                };
                
                process.ErrorDataReceived += (sender, args) =>
                {
                    if (!string.IsNullOrEmpty(args.Data))
                    {
                        outputBuilder.AppendLine(args.Data);
                        errorCallback?.Invoke(args.Data);
                    }
                };
                
                process.Exited += (sender, args) =>
                {
                    completedCallback?.Invoke();
                };
                
                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
            }
            catch (Exception ex)
            {
                errorCallback?.Invoke(ex.Message);
            }
        }
    }
}

6. 项目文件 (AdbTool.csproj)

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{YOUR-PROJECT-GUID}</ProjectGuid>
    <OutputType>WinExe</OutputType>
    <RootNamespace>AdbTool</RootNamespace>
    <AssemblyName>AdbTool</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="MainForm.cs" />
    <Compile Include="MainForm.Designer.cs" />
    <Compile Include="Adb\AdbManager.cs" />
    <Compile Include="Adb\DeviceInfo.cs" />
    <Compile Include="Adb\FileTransfer.cs" />
    <Compile Include="Adb\AppManager.cs" />
    <Compile Include="Adb\ScreenCapture.cs" />
    <Compile Include="Adb\LogCat.cs" />
    <Compile Include="Utils\ProcessExecutor.cs" />
    <Compile Include="Utils\AdbCommandBuilder.cs" />
    <Compile Include="Utils\ProgressReporter.cs" />
    <Compile Include="Models\Device.cs" />
    <Compile Include="Models\FileEntry.cs" />
    <Compile Include="Models\TransferProgress.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

参考代码 C#通过adb传输安卓设备数据 www.youwenfan.com/contentcsv/111958.html

三、使用说明

1. 环境准备

  1. 安装 Android SDK Platform-Tools

  2. 启用手机开发者模式

    • 手机设置 → 关于手机 → 连续点击版本号7次
    • 返回设置 → 开发者选项 → 启用 USB 调试
  3. 连接手机

    • 使用 USB 线连接手机和电脑
    • 在手机上授权电脑调试

2. 功能说明

功能 描述
设备连接 自动检测已连接的安卓设备
文件传输 双向文件传输(PC ↔ 手机)
APK管理 安装、卸载、启动应用
截图 实时截取手机屏幕
日志抓取 实时查看系统日志
Shell命令 执行任意ADB shell命令

3. 常用ADB命令速查

bash 复制代码
# 连接设备
adb devices

# 安装APK
adb install app.apk

# 卸载应用
adb uninstall com.example.app

# 截图
adb shell screencap /sdcard/screen.png

# 拉取文件
adb pull /sdcard/file.txt ./local/

# 推送文件
adb push ./local/file.txt /sdcard/

# 查看日志
adb logcat

# 执行shell命令
adb shell ls /sdcard/

4. 扩展功能建议

  1. 无线调试:支持通过WiFi连接设备
  2. 批量操作:同时对多台设备执行相同操作
  3. 自动化脚本:录制和执行自动化测试脚本
  4. 性能监控:实时显示CPU、内存、网络使用情况
  5. 备份还原:完整备份和恢复设备数据
相关推荐
飞猿_SIR1 小时前
RK3288 Android11平台移植RTL8733BU-WiFi模组
android·嵌入式硬件
xiaoshuaishuai81 小时前
C# 逆向分析Privazer
数据库·microsoft·c#
通信侠1 小时前
android相机热启动缓存帧解决方案(任务快照)
android·缓存·blur·tasksnapshot·mtkcam
BreezeDove1 小时前
【Android】Flutter命令超时无响应问题
android·flutter
baivfhpwxf20231 小时前
雷赛(Leadshine)EtherCAT 数字 I/O 模块(如 EMC-E5064-8)的状态指示灯(I/O 状态)说明
c#·wpf
Kapaseker2 小时前
Android 线程发展shi
android·kotlin
李斯维2 小时前
Jetpack 可观察数据容器 LiveData 的高级用法
android·android jetpack·androidx
天才少年曾牛2 小时前
Android新增服务添加selinux权限
android·java·frameworks
knighthood20012 小时前
ros2-quick-runner插件v0.0.4版本发布
android·java·开发语言