C++ C# windows封装adb命令源码

121 篇文章 4 订阅
41 篇文章 2 订阅

方法一:管道技术

最终需要的函数 

//cmd命令后面一定要加\n
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(); }

	//Sleep(1000);
	//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);
		//Sleep(1000);
		//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;  
			printf(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;
}

示例

	CString filePath = filePathArray.GetAt(i);

			CString out;
			int ret=pipe(CString("adb install -r \"" + filePath + "\"").GetBuffer(),out.GetBuffer(MAX_LENGTH));
			if (g_bResult=(ret==0 &&out.Find("") != -1)) { pWnd->ShowInfo("Install App" + CString(to_string(i + 1).c_str()) +"("+ filePath + ") Success"); }
			else { out.ReleaseBuffer(); pWnd->ShowInfo(out + "Failed to install app("+ filePath + "), possible reasons:\r\n1. Application not signed\r\n2. Application as test package\r\n3. Insufficient space\r\n4. Insufficient authority");  goto END; }

 

#include <stdio.h>
#include <Windows.h>
//cmd命令后面一定要加\n
DWORD pipe2(char* szBuffer,char *out, DWORD outLength)
{
	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) { printf("CreatePipe error:%d", 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, szBuffer, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);//创建cmd进程.默认寻找cmd进程.
	if (!bRet) { printf("CreateProcess error:%d", GetLastError()); return  GetLastError(); }

	//Sleep(1000);
	//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);
	} while (dwExitCode==STILL_ACTIVE);//等待子进程退出


	//6.读出响应
	//char pReadBuf[5000] = { 0 };
	//DWORD dataLength = sizeof(pReadBuf);
	//DWORD dwBytesRead;
	if (NULL == ReadFile(hParentRead, out, outLength-1, &outLength, NULL)) {  /*break;*/ } //读cmd显示内容
	if (outLength > 0) { printf(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 main()
{
	char out[5000] = { 0 };
	pipe2("cmd.exe /c \"adb devices\"", out,sizeof(out));
	//pipe_system("ver\n");
	//pipe_system("ipconfig\n");
	printf("end\n");
	getchar();
	return 0;
}

更多细节:https://blog.csdn.net/chenhao0568/article/details/122689444?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167592604816782429711993%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167592604816782429711993&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-10-122689444-null-null.blog_rank_default&utm_term=adb&spm=1018.2226.3001.4450一、共享内存管 道(Pipe)实际是用于进程间通信的一段共享内存。把管道想想成共享内存比较好理解。示例:把DOS进程上的内容通过管道技术输出到一个MFC应用程序的CEdit控件中。CreeatePipe(&hRead,&hWrite,&sa,0); //创建pipe内核对象,设置好hRead,hWrite.管道2:cmd进程输入重定向到hReadChild从这里读,把MFC命令dir写到hWriteParent里,cmd进程会执行这个命令。管道1:cmd进程输出重https://blog.csdn.net/chenhao0568/article/details/122689444?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167592604816782429711993%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=167592604816782429711993&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-10-122689444-null-null.blog_rank_default&utm_term=adb&spm=1018.2226.3001.4450

方法二:_POPEN等简单

但是下面没法获取console提示的错误 

// crt_popen.c  
/* This program uses _popen and _pclose to receive a
 * stream of text from a system process.
 */

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>
#include <errno.h>
int main(void)
{

	char   psBuffer[128];
	FILE   *pPipe;

	/* Run DIR so that it writes its output to a pipe. Open this
	 * pipe with read text attribute so that we can read it
	 * like a text file.
	 */

	if ((pPipe = _popen("adb install -r \"D:\\test2\\ErrorTest.apk\"", "rt")) == NULL)
		exit(1);

	/* Read pipe until end of file, or an error occurs. */
	while (fgets(psBuffer, 128, pPipe))
	{
		printf(psBuffer);
	}
	/* Close pipe and print return value of pPipe. */
	if (feof(pPipe))
	{
		printf("\nProcess returned %d\n", _pclose(pPipe));
	}
	else
	{
		printf("Error: Failed to read the pipe to the end.\n");
	}
	getchar();
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Java中封装ADB命令的步骤如下所示: 1. 首先,创建一个指向ADB目标的指令类,这样可以方便地执行ADB命令。 2. 下载ADB程序到PC,并将其放入项目目录下的adb文件夹内。这样可以确保ADB程序可用并与Java项目相连。 3. 创建一个临时文件夹,用于保存从Android设备中导出的文件。这可以通过创建一个名为"tem"的文件夹来实现。 4. 创建工具类代码,用于执行ADB命令。这个工具类可以包含执行ADB命令的方法,例如执行"adb shell"命令等。 5. 导入文件代码,用于将文件从Android设备中导出到临时文件夹。这可以通过使用"adb pull"命令实现。 6. 完成以上步骤后,您就可以在Java项目中使用封装ADB命令了。您可以调用相应的方法来执行特定的ADB命令,如"adb shell"或"adb pull"等。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [java中实现adb命令 | 学步园](https://blog.csdn.net/weixin_32512261/article/details/114056810)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [java 封装一个ADB](https://blog.csdn.net/qq_41054313/article/details/94555050)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小黄人软件

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

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

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

打赏作者

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

抵扣说明:

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

余额充值