Qt5.9调用Windows的匿名管道总结

本文介绍如何在Qt环境下使用Windows API函数CreatePipe创建匿名管道,并结合CreateProcess启动进程,实现从命令行获取输出。通过封装的executeCmd函数,可执行任意cmd命令并获取其结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

匿名管道一般用于两个父子进程之间的通信,通常是在MFC上调用。在Windows上,匿名管道的调用函数为CreatePipe(),具体的原理讲解和调用实例,可以参考博主的这篇博客:https://blog.csdn.net/naibozhuan3744/article/details/83142860

本博客主要总结在Qt下调用Windows系统函数CreatePipe()创建一个管道,然后启动一个进程。该进程的输出连接管道的写端写入数据。然后调用Windows系统函数ReadFile()连接管道的读端口,读取管道的内容,然后返回该内容。

 

1.1具体的封装函数总结如下:

QString executeCmd(QString cmdLine)
{
    //创建匿名管道
    HANDLE hReadPipe, hWritePipe;
    SECURITY_ATTRIBUTES safety;						//安全属性
    safety.nLength = sizeof(SECURITY_ATTRIBUTES);	//结构体大小
    safety.lpSecurityDescriptor = NULL;				//安全描述符,NULL;使用默认的
    safety.bInheritHandle = TRUE;					//安全描述符的对象能否被子进程继承
    if (!CreatePipe(&hReadPipe, &hWritePipe, &safety, 0))
    {
        //创建管道错误
        return QString(tr("创建管道错误!"));
    }

    //创建进程
    TCHAR *cmdStr = QStringToTChar(cmdLine);
    STARTUPINFO startupInfo;
    startupInfo.cb= sizeof(STARTUPINFO);     //指字本结构的长度,总是被设为sizeof(STARTUPINFO);
    startupInfo.lpDesktop = NULL;  //指定桌面名称
    startupInfo.lpTitle = NULL;   //控制台窗口标题
    startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;  //使用wSHOWWIndows成员
    startupInfo.wShowWindow = SW_HIDE;//窗口的显示方式,TRUE和FALSE
    startupInfo.cbReserved2 =0; //保留C运行库必须为零
    startupInfo.lpReserved2 =0;//保留C运行库必须为零
    startupInfo.dwXCountChars =0;  //指定控制台窗口的行数
    startupInfo.dwYCountChars =0;
    startupInfo.dwFillAttribute =0; //窗口背景颜色
    startupInfo.hStdError = hWritePipe; //标志控制台窗口缓存
    startupInfo.hStdInput =NULL;
    startupInfo.hStdOutput = hWritePipe;
    startupInfo.dwX =0;   //指定新创建窗口的位置坐标(dwx,dwy)
    startupInfo.dwY =0;
    startupInfo.dwXSize = 0; //指定新创建窗口大小信息
    startupInfo.dwYSize =0;
    PROCESS_INFORMATION pinfo;
    if (!CreateProcess(NULL, cmdStr, NULL, NULL, TRUE, NULL, NULL, NULL, &startupInfo, &pinfo))
    {
        //创建进程错误
        return QString(tr("创建进程错误!"));
    }
    CloseHandle(hWritePipe);

    //获取管道信息
    char buffer[4096];
    DWORD byteRead;
    QString output;									//返回值
    while (true)
    {
        memset(buffer, 0, 4096);
        if (!ReadFile(hReadPipe, buffer, 4095, &byteRead, NULL))
        {
            break;
        }
        output.append(QString::fromUtf8(buffer));   //char*转QString
    }
    CloseHandle(hReadPipe);
    return output;
}
TCHAR *QStringToTChar(const QString &str)
{
    QByteArray ba = str.toUtf8();
    char *data = ba.data(); //以上两步不能直接简化为“char *data = str.toUtf8().data();”
    int charLen = strlen(data);
    int len = MultiByteToWideChar(CP_ACP, 0, data, charLen, NULL, 0);
    TCHAR *buf = new TCHAR[len + 1];
    MultiByteToWideChar(CP_ACP, 0, data, charLen, buf, len);
    buf[len] = '\0';
    return buf;
}

函数QString executeCmd(QString cmdLine)的功能是输入cmd命令行,输出命令行运行结果。(有一个bug,输出内容中文显示乱码)
函数TCHAR *QStringToTChar(const QString &str)的功能是将QString转为TCHAR。

 

1.2函数调用实例

由于把函数executeCmd()变为一个单例类的成员函数,所以调用方法如下。

qDebug()<<QGlobalClass::GetInstance()->executeCmd("ipconfig /?");

 

1.3程序运行结果如下图所示

 

 

 

参考内容:

https://blog.csdn.net/lance710825/article/details/78330838(参考:QString转TCHAR)

https://blog.csdn.net/JILVAN21/article/details/80646008(参考:Qt的MinGW调用Windows函数)

https://blog.csdn.net/naibozhuan3744/article/details/83142860(参考:MFC下实例匿名管道实例)

https://blog.csdn.net/Blanlaile/article/details/41176541(参考:STARTUPINFO结构体参数初始化)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三公子Tjq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值