无论是在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
);
4、CreateProcessW() ==》 可使用管理员权限,无法直接获取返回信息,可判断是否执行成功。
附一个封装的基于CreateProcessW 的方法,支持阻塞模式。
bool RunProgram(QString exePath, QString args, bool bWaitFor)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
exePath = exePath + " " + args;
if (!CreateProcessW(nullptr, // No module name (use command line)
const_cast<LPWSTR>(exePath.toStdWString().c_str()), // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NO_WINDOW, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return false;
}
if (bWaitFor)
{
WaitForSingleObject(pi.hProcess, INFINITE);
//Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return true;
}
显然,在我们渴望获取到指令返回的信息时,以上的几种方法都不如人意。考虑到‘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:user@domain.microsoft.com "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;
}
分类:
C++/C
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2022-06-07 代理服务器客户端Proxifier使用教程 Proxifier图文设置
2018-06-07 利用cbmakegen导出Code::blocks的Makefile
2016-06-07 linux下如何获取某一进程占用的物理内存和虚拟内存
2016-06-07 linux下如何获取每个线程的CPU占用率
2016-06-07 内存问题排查手段及相关文件介绍
2016-06-07 嵌入式/X86下linux系统死机及内存优化
2016-06-07 gcc指定头文件路径及动态链接库路径