方法一:管道技术
最终需要的函数
//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;
}
方法二:_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();
}