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. 环境准备
-
安装 Android SDK Platform-Tools
- 下载地址: developer.android.com/studio/releases/platform-tools
- 解压后将
platform-tools目录添加到系统 PATH 环境变量
-
启用手机开发者模式
- 手机设置 → 关于手机 → 连续点击版本号7次
- 返回设置 → 开发者选项 → 启用 USB 调试
-
连接手机
- 使用 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. 扩展功能建议
- 无线调试:支持通过WiFi连接设备
- 批量操作:同时对多台设备执行相同操作
- 自动化脚本:录制和执行自动化测试脚本
- 性能监控:实时显示CPU、内存、网络使用情况
- 备份还原:完整备份和恢复设备数据