DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

无论是在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;
}
posted on   DoubleLi  阅读(1316)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源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指定头文件路径及动态链接库路径
点击右上角即可分享
微信分享提示