無論是在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;
}