windows/Linux c++ 获取CMD指令执行的返回结果

 无论是在windows还是linux下我们都可以借助popen执行终端指令并获取到返回值。

/// 执行cmd指令并返回结果
string getCmdResult(const string &strCmd)  
{
    char buf[10240] = {0};
    FILE *pf = NULL;

    if( (pf = popen(strCmd.c_str(), "r")) == NULL )
    {
        return "";
    }

    string strResult;
    while(fgets(buf, sizeof buf, pf))
    {
        strResult += buf;
    }

    pclose(pf);

    unsigned int iSize =  strResult.size();
    if(iSize > 0 && strResult[iSize - 1] == '\n')  // linux
    {
        strResult = strResult.substr(0, iSize - 1);
    }

    return strResult;
}

但是值得注意的是,windows下诸多的指令需要管理员的权限才能执行,这是很令人头疼的。

除了上述方法外,我们先大致罗列下windows下可以执行命令行指令的方法:

1、WinExec() ==》无法直接使用管理员权限,无法获取返回信息,只能判断是否执行

 QString cmdstr = QString("cmd /c taskkill /im iphelper.exe /t /f");
 WinExec(cmdstr.toLatin1().data(), SW_HIDE);

2、ShellExecute()==》可使用管理员权限,无法获取返回信息

ShellExecute(0,"runas", LPCSTR("cmd.exe"),LPCSTR("/c net user administrator /active:yes"),"",SW_HIDE);

3、CreateProcessAsUser()==》可使用管理员权限,无法获取返回信息,可判断是否执行成功

 BOOL CreateProcessAsUser(
  HANDLE hToken,         // handle to a token representing the logged-on user
  LPCTSTR lpApplicationName,  // pointer to name of executable module
  LPTSTR lpCommandLine,       // pointer to command line string
  LPSECURITY_ATTRIBUTES lpProcessAttributes, // process security attributes
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // thread security attributes
  BOOL bInheritHandles,         // whether new process inherits handles
  DWORD dwCreationFlags,        // creation flags
  LPVOID lpEnvironment,         // pointer to new environment block
  LPCTSTR lpCurrentDirectory,   // pointer to current directory name
  LPSTARTUPINFO lpStartupInfo,  // pointer to STARTUPINFO
  LPPROCESS_INFORMATION lpProcessInformation  // pointer to PROCESS_INFORMATION
);

显然,在我们渴望获取到指令返回的信息时,以上的几种方法都不如人意。考虑到‘runas’方法,那么我们能否既使用管理员权限执行指令的同时获取到指令执行返回结果信息呢?答案是肯定的。

先熟悉下windows的runas指令:

RUNAS 用法:

RUNAS [ [/noprofile | /profile] [/env] [/savecred | /netonly] ]
        /user:<UserName> program

RUNAS [ [/noprofile | /profile] [/env] [/savecred] ]
        /smartcard [/user:<UserName>] program

RUNAS /trustlevel:<TrustLevel> program

   /noprofile        指定不应该加载用户的配置文件。
                     这会加速应用程序加载,但
                     可能会造成一些应用程序运行不正常。
   /profile          指定应该加载用户的配置文件。
                     这是默认值。
   /env              要使用当前环境,而不是用户的环境。
   /netonly          只在指定的凭据限于远程访问的情况下才使用。
   /savecred         用用户以前保存的凭据。
   /smartcard        如果凭据是智能卡提供的,则使用这个选项。
   /user             <UserName> 应使用 USER@DOMAIN 或 DOMAIN\USER 形式
   /showtrustlevels  显示可以用作 /trustlevel 的参数的
                     信任级别。
   /trustlevel       <Level> 应该是在 /showtrustlevels 中枚举
                     的一个级别。
   program           EXE 的命令行。请参阅下面的例子

示例:
> runas /noprofile /user:mymachine\administrator cmd
> runas /profile /env /user:mydomain\admin "mmc %windir%\system32\dsa.msc"
> runas /env /user:[email protected] "notepad \"my file.txt\""

注意:  只在得到提示时才输入用户的密码。
注意:  /profile 跟 /netonly 不兼容。
注意:  /savecred 跟 /smartcard 不兼容。

 

那么方法就有了,只需要在使用getCmdResult()函数时,我们在传参strCmd中借用runas指定程序使用管理员权限执行即可。

    string cmd = string("runas /noprofile /user:mymachine\\administrator \"cmd /c ") + "cmd /c chcp 65001 && ping www.baidu.com -n 1 -w 1000" + "\"";
    strRe = getCmdResult(cmd);
    cout << strRe << endl;

完整的测试代码如下:

#include <iostream>

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

using namespace std;

/// 执行cmd指令并返回结果
string getCmdResult(const string &strCmd)  
{
    char buf[10240] = {0};
    FILE *pf = NULL;

    if( (pf = popen(strCmd.c_str(), "r")) == NULL )
    {
        return "";
    }

    string strResult;
    while(fgets(buf, sizeof buf, pf))
    {
        strResult += buf;
    }

    pclose(pf);

    unsigned int iSize =  strResult.size();
    if(iSize > 0 && strResult[iSize - 1] == '\n')  // linux
    {
        strResult = strResult.substr(0, iSize - 1);
    }

    return strResult;
}


int main(int argc, char *argv[])
{

    /// 获取ping指令的结果
    string strCmd = "cmd /c chcp 65001 && ping www.baidu.com -n 1 -w 1000";

    string strRe = getCmdResult(strCmd);
    cout << strRe << endl;

    /// 以管理员的身份运行程序并返回结果
    /// runas
    string cmd = string("runas /noprofile /user:mymachine\\administrator \"cmd /c ") + "cmd /c chcp 65001 && ping www.baidu.com -n 1 -w 1000" + "\"";
    strRe = getCmdResult(cmd);
    cout << strRe << endl;

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章