匿名管道一般用于两个父子进程之间的通信,通常是在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结构体参数初始化)