C# adb命令封装类 获取响应等 及C++版封装CMD命令匿名管道 两应用间交互

46 篇文章 1 订阅
该代码实现了一个名为Adb的类,用于与Android设备进行交互,包括启动服务器、重连、连接和断开设备、安装和卸载应用、获取设备列表、检查设备状态、启动活动以及获取设备属性等。类中包含了事件处理方法,支持输出数据和错误的回调。
摘要由CSDN通过智能技术生成

 

 

using ApkManager.Lib;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ApkManager
{
    public class Adb
    {
        public class Device
        {
            public string Name { get; set; }
            public string Android { get; set; }
            public string Abi { get; set; }
            public int Sdk { get; set; }

            public override string ToString()
            {
                return Name.ToString();
            }
        }

        private static bool OVERRIDE_ONREPORTEVENT = false;
        private static bool OVERRIDE_ONPROCESSEVENT = false;

        public delegate void ProcessEventHandler(bool value);

        public event ProcessEventHandler OnProcess;

        public delegate void OutputEventHander(string message);

        public event OutputEventHander OutputDataReceived;

        public delegate void ErrorEventHandler(string message);

        public event ErrorEventHandler ErrorDataReceived;

        public Adb()
        {
        }

        private async Task<string> RunAsync(string command, params object[] args)
        {
            using (var p = new Process())
            {
                var OutputMessage = string.Empty;
                p.OutputDataReceived += (s, e) => {
                    if (string.IsNullOrWhiteSpace(e.Data)) return;
                    OutputMessage += e.Data + Environment.NewLine;
                    if (!OVERRIDE_ONREPORTEVENT)
                        OutputDataReceived?.Invoke(e.Data);
                };

                var ErrorMessage = string.Empty;
                p.ErrorDataReceived += (s, e) => {
                    if (string.IsNullOrWhiteSpace(e.Data)) return;
                    ErrorMessage += e.Data + Environment.NewLine;
                    if (!OVERRIDE_ONREPORTEVENT)
                        ErrorDataReceived?.Invoke(e.Data);
                };

                p.StartInfo = new ProcessStartInfo()
                {
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    WindowStyle = ProcessWindowStyle.Hidden,
                    FileName = Path.Combine("Lib", "adb.exe"),
                    Arguments = string.Format(command, args)
                };

                p.Start();

                Debug.Print("Adb.Command: adb {0}", string.Format(command, args));

                if (!OVERRIDE_ONPROCESSEVENT)
                    OnProcess?.Invoke(true);

                p.BeginOutputReadLine();
                p.BeginErrorReadLine();

                await Task.Run(() => p.WaitForExit());

                if (!OVERRIDE_ONPROCESSEVENT)
                    OnProcess?.Invoke(false);

                if (p.ExitCode != 0) throw new Exception(ErrorMessage);

                Debug.Print("Adb.Output: {0}", OutputMessage);
                return OutputMessage;
            };
        }

        public async Task<bool> StartServer()
        {
            try
            {
                await RunAsync("start-server");
                return true;
            }
            catch (Exception e)
            {
                Debug.Print("Adb.StartServer: {0}", e.Message);
                return false;
            }
        }

        public async Task<bool> Reconnect()
        {
            try
            {
                await RunAsync("reconnect");
                return true;
            }
            catch (Exception e)
            {
                Debug.Print("Adb.Reconnect: {0}", e.Message);
                return false;
            }
        }

        public async Task<bool> Connect(string address)
        {
            try
            {
                if (!address.Contains(":"))
                    address += ":5555";

                var result = await RunAsync("connect {0}", address);
                return result.Contains("connected");
            }
            catch (Exception e)
            {
                Debug.Print("Adb.Connect: {0}", e.Message);
                return false;
            }
        }

        public async Task<bool> Disconnect(string address)
        {
            try
            {
                if (!address.Contains(":"))
                    address += ":5555";

                var result = await RunAsync("disconnect {0}", address);
                return result.Contains("disconnected") || result.Contains("no such device");
            }
            catch (Exception e)
            {
                Debug.Print("Adb.Disconnect: {0}", e.Message);
                return false;
            }
        }

        public async Task<List<string>> GetDevices()
        {
            var devices = new List<string>();

            try
            {
                var result = await RunAsync("devices");
                var matches = Regex.Matches(result, @"(.+?)\tdevice");
                foreach (Match match in matches)
                {
                    devices.Add(match.Groups[1].Value);
                }
            }
            catch (Exception e)
            {
                Debug.Print("Adb.GetDevices: {0}", e.Message);
            }

            return devices;
        }

        public async Task<bool> Install(string device, string pathApk)
        {
            try
            {
                var result = await RunAsync("-s {0} install -r \"{1}\"", device, pathApk.GetShortPathName());
                return result.Contains("Success");
            }
            catch (Exception e)
            {
                Debug.Print("Adb.Install: {0}", e.Message);
                return false;
            }
        }

        public async Task<bool> Uninstall(string device, string package, bool keepData = false)
        {
            try
            {
                var command = keepData ? $"-s {device} shell pm uninstall -k {package}" : $"-s {device} uninstall {package}";
                var result = await RunAsync(command);
                return result.Contains("Success");
            }
            catch (Exception e)
            {
                Debug.Print("Adb.Uninstall: {0}", e.Message);
                return false;
            }
        }

        public async Task<bool> IsDeviceOnline(string device)
        {
            try
            {
                OVERRIDE_ONREPORTEVENT = true;
                var result = await RunAsync("-s {0} get-state", device);
                return result.ToLower().Contains("device");
            }
            catch (Exception e)
            {
                Debug.Print("Adb.IsDeviceOnline: {0}", e.Message);
                return false;
            }
            finally
            {
                OVERRIDE_ONREPORTEVENT = false;
            }
        }

        public async Task<bool> LaunchActivity(string device, Apk apk)
        {
            try
            {
                var result = await RunAsync("-s {0} shell am start -n \"{1}/{2}\" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER", device, apk.PackageName, apk.LaunchableActivity);
                return result.ToLower().Contains("error");
            }
            catch (Exception e)
            {
                Debug.Print("Adb.LunchActivity: {0}", e.Message);
                return false;
            }
        }

        public async Task<string> GetProp(string device, string prop)
        {
            try
            {
                var result = await RunAsync("-s {0} shell getprop {1}", device, prop);
                return string.IsNullOrWhiteSpace(result) ? "Unknown" : result.Trim();
            }
            catch (Exception e)
            {
                Debug.Print("Adb.Uninstall: {0}", e.Message);
                return "Unknown";
            }
        }

        public async Task<Device> GetDevice(string address)
        {
            OVERRIDE_ONPROCESSEVENT = true;
            OnProcess?.Invoke(true);

            var name = await GetProp(address, "ro.product.model");
            if (string.IsNullOrWhiteSpace(name))
                name = await GetProp(address, "ro.product.brand");
            if (string.IsNullOrWhiteSpace(name))
                name = await GetProp(address, "ro.product.device");
            if (string.IsNullOrWhiteSpace(name))
                name = "Unknown";

            var android = await GetProp(address, "ro.build.version.release");
            if (string.IsNullOrWhiteSpace(android))
                android = "Unknown";

            var sdk = await GetProp(address, "ro.build.version.sdk");
            int.TryParse(sdk, out int _sdk);

            var _abi = await GetProp(address, "ro.product.cpu.abi");

            OnProcess?.Invoke(false);
            OVERRIDE_ONPROCESSEVENT = false;

            return new Device()
            {
                Name = name,
                Android = android,
                Sdk = _sdk,
                Abi = _abi
            };
        }
    }
}

调用示例

using ApkManager;
using System;
using System.Windows.Forms;
using System.Windows.Threading;

namespace FT_Tools
{
    public partial class FormT20WriteConfig : Form
    {
        private void FormT20WriteConfig_Load(object sender, EventArgs e)
        {

            // define adb
            adb = new Adb();
            adb.OnProcess += (value) => ShowLoading(value);
            adb.OutputDataReceived += (msg) => CommandOutput_Insert(msg, false);
            adb.ErrorDataReceived += (msg) => CommandOutput_Insert(msg, true);
        }
        private Adb adb;
        private async void buttonStart_Click(object sender, EventArgs e)
        {
            var devices = await adb.GetDevices();
            foreach (var device in devices)
            {
                Log("Connected to:"+device);
                //cbDevices.Items.Add(device);
            }
        }
        private void CommandOutput_Insert(string message, bool error = false)
        {
            Log(message);
            //Dispatcher.Invoke(() =>
            //{
            //    var color = Brushes.WhiteSmoke;
            //    if (error || message.ToLower().Contains("failed"))
            //        color = Brushes.IndianRed;
            //    else if (message.ToLower().Contains("success"))
            //        color = Brushes.LightBlue;

            //    var item = new ListBoxItem()
            //    {
            //        Content = message.Trim(),
            //        Background = color
            //    };
            //    lbOutput.Items.Add(item);
            //    lbOutput.ScrollIntoView(item);
            //});
        }
        private void ShowLoading(bool state = true)
        {
            Log("ShowLoading:" + state);
            //Dispatcher.Invoke(() =>
            //{
            //    isLoading = state;
            //    PanelLoading.Visibility = state ? Visibility.Visible : Visibility.Collapsed;
            //});
        }
        public FormT20WriteConfig()
        {
            InitializeComponent();
        }    
        public void Log(string str)
        {
            MyLog.MyLog.WriteLogs(MyLog.MyLog.fileName, "", str);
            this.Invoke((EventHandler)(delegate
            {
                textBoxLog.Text += str + "\r\n";
                textBoxLog.SelectionStart = textBoxLog.Text.Length;
                textBoxLog.ScrollToCaret();
            }));
        }

    }
}

C++版

#define MAX_LENGTH 22048
int pipe(char *cmd, char *out)
{
	logger.INFO_F(cmd);
	HANDLE hParentRead, hChildWrite; //创建2个句柄 父(当前应用)读子(cmd)写

	//1.创建一个安全属性描述符,设置句柄可继承
	SECURITY_ATTRIBUTES sa = { 0 };                //安全属性描述符        
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;                      //设置句柄可继承

	//2.创建两个管道.父读->子写 子读->父写的
	BOOL bRet = CreatePipe(&hParentRead, &hChildWrite, &sa, 0); //创建管道1. 父进程读 -> 子进程写入
	if (!bRet) { logger.ERROR_F("CreatePipe error:" + to_string(GetLastError())); return  GetLastError(); }

	//bRet = CreatePipe(&hChildRead, &hParentWrite, &sa, 0);//创建管道2.  子进程读->父进程写.
	//if (!bRet) { printf("error:%d", GetLastError()); return bRet; }

	PROCESS_INFORMATION pi = { 0 };                 //进程信息结构体
	STARTUPINFO si = { 0 };                         //启动信息结构体
	si.cb = sizeof(si);
	//3.重定向输出, 将子进程的读 以及子进程的写重定向.
	//si.hStdInput = hChildRead;    //将子进程读取重定向到stdinput中
	si.hStdOutput = hChildWrite;  //将子进程写重定向到 stdout中. 
	si.hStdError = hChildWrite;  //将子进程写重定向到 stdout中. 
	si.dwFlags = STARTF_USESTDHANDLES;   //设置窗口隐藏启动
	//4.创建子进程
	bRet = CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);//创建cmd进程.默认寻找cmd进程.
	if (!bRet) { logger.ERROR_F("CreateProcess error:" + to_string(GetLastError())); return  GetLastError(); }


	//DWORD dwFileSize = GetFileSize(hParentRead, NULL); //可以把头长度去掉

	//char szBuffer[] = "ver\n";
	//5.写入命令数据给子进程.
	//DWORD dwWrite = 0; //实际写入字节数
	//bRet = WriteFile(hParentWrite, szBuffer, strlen(szBuffer), &dwWrite, 0);//使用writeFile操作管道,给cmd发送数据命令.
	//if (!bRet) { printf("error:%d", GetLastError()); return bRet; }

	CloseHandle(pi.hThread); //关闭句柄
	CloseHandle(hChildWrite);//关闭write ReadFile才不会阻塞
	DWORD dwExitCode;
	do {
		GetExitCodeProcess(pi.hProcess, &dwExitCode);

		//printf("GetExitCodeProcess:%d\n", dwExitCode);

		char psBuffer[128] = { 0 };
		DWORD outLength = 0;
		if (NULL == ReadFile(hParentRead, psBuffer, sizeof(psBuffer) - 1, &outLength, NULL)) { logger.INFO_F(FUN_LINE"NULL " + to_string(GetLastError())); } //读cmd显示内容
		if (outLength > 0) {
			psBuffer[outLength] = 0;
			logger.INFO_F(psBuffer);
			if (strlen(out) > MAX_LENGTH / 2) { memset(out, 0, sizeof(MAX_LENGTH)); }
			strcat(out, psBuffer);
		}
	} while (dwExitCode == STILL_ACTIVE);//等待子进程退出


	//6.读出响应
	//DWORD outLength;
	//if (NULL == ReadFile(hParentRead, out, MAX_LENGTH - 1, &outLength, NULL)) {  /*break;*/ } //读cmd显示内容
	//if (outLength > 0) { out[outLength] = 0;  logger.INFO_F(out); }

	//7.退出子进程 退出cmd
	//char *exit="exit\n"; 
	//WriteFile(hParentWrite, exit, strlen(exit), NULL, 0);//使用writeFile操作管道,给cmd发送数据命令.
	//if (!bRet) { printf("error:%d", GetLastError()); return bRet; }

	TerminateProcess(pi.hProcess, 0); //退出子进程
	//CloseHandle(hParentWrite); //关闭写入句柄
	CloseHandle(hParentRead);
	CloseHandle(pi.hProcess);
	//CloseHandle(hChildRead);
	//CloseHandle(pi.hProcess);
	//printf("end\n");
	return dwExitCode;
}
int pipe_cmd(char *cmd, char *out)
{
	return pipe(CString("cmd.exe /c \"" + CString(cmd) + "\"").GetBuffer(), out);
}
int ADBHandShake()
{
	CString out;
	pipe("adb shell getprop ro.product.model", out.GetBuffer(MAX_LENGTH));
	int ret = pipe(CString("adb shell getprop ro.product.model").GetBuffer(), out.GetBuffer(MAX_LENGTH));
	if ((ret == 0 && out.Find("\n") != -1)) { logger.INFO_F("Connect to device via ADB. ");  return 0; }
	else { logger.ERROR_F("Failed to connect device via ADB. ret=" + to_string(ret)); }
	return -100;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄人软件

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值