C程序中获得命令行输出结果

在c程序中,system函数可以运行命令行,但是只能得到该命令行的int型返回值,并不能获得显示结果。例如system(“ls”)只能得到0或非0,如果要获得ls的执行结果,则要通过管道来完成的。首先用popen打开一个命令行的管道,然后通过fgets获得该管道传输的内容,也就是命令行运行的结果

在linux上运行的例子如下:

  1. void executeCMD(const char *cmd, char *result)   
  2. {   
  3.     char buf_ps[1024];   
  4.     char ps[1024]={0};   
  5.     FILE *ptr;   
  6.     strcpy(ps, cmd);   
  7.     if((ptr=popen(ps, "r"))!=NULL)   
  8.     {   
  9.         while(fgets(buf_ps, 1024, ptr)!=NULL)   
  10.         {   
  11.            strcat(result, buf_ps);   
  12.            if(strlen(result)>1024)   
  13.                break;   
  14.         }   
  15.         pclose(ptr);   
  16.         ptr = NULL;   
  17.     }   
  18.     else  
  19.     {   
  20.         printf("popen %s error\n", ps);   
  21.     }   
  22. }  

在这段代码中,参数cmd为要执行的命令行,result为命令行运行结果。输入的cmd命令最好用... 2>&1 的形式,这样将标准错误也读进来

在windows上相对要麻烦些,需要用CreateProcessW函数来启动新的进程,以便执行cmd命令。windows下的例子请看这个调用md5sum.exe来获得文件md5值的代码:

  1. int GetFileMD5W(const TCHAR *filefullpath, char *MD5key)   
  2. {   
  3.     TCHAR szfilenameW[MAX_PATH_LENGTH]={0};   //保存文件名   
  4.     TCHAR szFilePathW[MAX_PATH_LENGTH]={0};   //保存路径   
  5.     TCHAR szCmdLineW[MAX_PATH_LENGTH]={0};    //保存命令行信息   
  6.     char buffer[MAX_PATH_LENGTH] = {0};       //保存命令行输出   
  7.     TCHAR *pos=NULL;   
  8.     DWORD bytesRead = 0;    
  9.     if (wcslen(filefullpath)>MAX_PATH_LENGTH)   
  10.         return false;   
  11.     wcscpy(szFilePathW, filefullpath);   
  12.     int i=0;   
  13.     while (szFilePathW[i]!=0)   
  14.     {   
  15.         if (szFilePathW[i]==_T('/'))   
  16.             szFilePathW[i]=_T('\\');   
  17.         i++;   
  18.     }   
  19.     if ((pos=wcschr(szFilePathW, '\\'))==NULL)   //找到文件路径最右边的'\'   
  20.     {   
  21.         return false;   
  22.     }   
  23.       
  24.     wcscpy(szfilenameW, pos+1);                  //获得文件名   
  25.     *pos=0;                                      //获得文件所在路径   
  26.     if (wcslen(szfilenameW)==0 || wcslen(szFilePathW)==0 || MD5key==NULL)  //检查文件名或路径大小是否合适   
  27.     {   
  28.         return false;   
  29.     }   
  30.     wsprintf(szCmdLineW,L"cmd.exe /c md5sum \"%s\" ",szfilenameW);       //给出命令行信息   
  31.         //eg: cmd.exe /c md5sum "for text.txt"   
  32.     SECURITY_ATTRIBUTES sa = {0};                                              
  33.     HANDLE hRead = NULL, hWrite = NULL;                                  //设置管道读写句柄   
  34.     sa.nLength = sizeof(SECURITY_ATTRIBUTES);    
  35.     sa.lpSecurityDescriptor = NULL;    
  36.     sa.bInheritHandle = TRUE;    
  37.     if (!CreatePipe(&hRead, &hWrite, &sa,0))                             //创建管道   
  38.     {    
  39.         return false;    
  40.     }    
  41.     STARTUPINFO si = {0};    
  42.     PROCESS_INFORMATION pi = {0};    
  43.     si.cb = sizeof(STARTUPINFO);    
  44.     GetStartupInfo(&si);   
  45.     si.hStdError = hWrite;                                              //   
  46.     si.hStdOutput = hWrite;                                             //   
  47.     si.wShowWindow = SW_HIDE;    
  48.     si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;    
  49.     //关键步骤,CreateProcess函数参数意义请查阅MSDN    
  50.     if (!CreateProcessW(NULL, szCmdLineW    
  51.         ,NULL,NULL,TRUE,NULL,NULL,szFilePathW,&si,π))             //注意,这里将szFilePathW(文件所在路径)作为倒数第三个参数   
  52.     {    
  53.         CloseHandle(hWrite);   
  54.         CloseHandle(hRead);   
  55.         return false;   
  56.     }    
  57.     WaitForSingleObject(pi.hProcess,INFINITE);                         //等待md5sum结束   
  58.     //   Close   process   and   thread   handles.       
  59.     CloseHandle(pi.hProcess);                                          //关闭新进程的主线程   
  60.     CloseHandle(pi.hThread);                                        //关闭新进程   
  61.     CloseHandle(hWrite);                                               //关闭管道的写句柄   
  62.     ReadFile(hRead, buffer, MAX_PATH_LENGTH, &bytesRead, NULL);        //从管道中读取md5sum的运行结果   
  63.     CloseHandle(hRead);                                                //关闭管道的读句柄   
  64.     if (NULL!=strstr(buffer,"md5sum"))                                 //如果运行结果中出现了md5sum,多半是执行失败   
  65.     {   
  66.         //TRACE(buffer);   
  67.         return -2;   
  68.     }   
  69.     else if (!strnicmp(buffer,"No such file:",strlen("No such file:"))) //找不到制定文件   
  70.     {   
  71.         //TRACE(buffer);   
  72.         return -1;   
  73.     }   
  74.     if (strlen(buffer)<32)                                              //获得结果小于32位,说明没有得到md5值   
  75.     {   
  76.         //TRACE(buffer);   
  77.         return false;   
  78.     }   
  79.     strncpy(MD5key, buffer, 32);                                        //获得md5值成功   
  80.     strcat(MD5key, "\0");   
  81.     return TRUE;   
  82. }  

相关推荐