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;
}

 

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