源码
bool PipeCmd::createProcessOfCmd(QString pCommandLine)
{
TCHAR cmd[512];
wcscpy(cmd, (wchar_t*)pCommandLine.utf16());
HANDLE hRead = NULL, hWrite = NULL;
// 设定管道的安全属性
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
sa.bInheritHandle = TRUE; //创建的进程继承句柄
if (!CreatePipe(&hRead, &hWrite, &sa, 0)) //创建匿名管道
{
std::cout << "CreatePipe error" << std::endl;
return false;
}
STARTUPINFO si;
PROCESS_INFORMATION pi = { 0 };
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite; //新创建进程的标准输出连在写管道一端
si.wShowWindow = SW_HIDE; //隐藏窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))//创建子进程
{
if (cmd)
delete cmd;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(hRead);
CloseHandle(hWrite);
std::cout << "CreateProcess error" << std::endl;
return false;
}
DWORD dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
switch (dwRet)
{
case WAIT_TIMEOUT:
case WAIT_FAILED:
return false;
case WAIT_OBJECT_0:
CloseHandle(hWrite);//close hInPut handle ,make hte write pipe completes
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
char buffer[4096] = { 0 };
int len = 0;
DWORD readByte = 0;
BOOL hResult;
memset(buffer, 0, sizeof(buffer));
do
{
//a write operation completes on the write end of the pipe,so ReadFile can begin
hResult = ReadFile(hRead, buffer + len, 1024, &readByte, NULL);
len += readByte;
Sleep(200);
} while (readByte != 0 && hResult);
std::cout << buffer << std::endl;
CloseHandle(hRead);
return true;
}
下面讲解
匿名管道
介绍:略
设定管道的属性
HANDLE hRead= NULL,hWrite= NULL;
// 设定管道的安全属性
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
sa.bInheritHandle = TRUE; //创建的进程继承句柄
if (!CreatePipe(&hRead,&hWrite,&sa,0)) //创建匿名管道
{
MessageBox("CreatePipe Failed!","提示",MB_OK | MB_ICONWARNING);
return;
}
参数说明
SECURITY_ATTRIBUTES | 结构 |
---|---|
bInheritHandle | 确定在创建新进程时是否继承返回的句柄。 如果此字段设置为非零值,则新进程将继承句柄。 如果为0,则新进程不会继承句柄。 |
lpSecurityDescriptor | 指向 SECURITY_DESCRIPTOR 结构的指针,该结构控制对对象的访问。 如果此成员的值为 null ,则为对象分配与调用进程的访问令牌关联的默认安全描述符。 这不同于通过分配 null (DACL) 的自由访问控制列表来向每个人授予访问权限。 进程的访问令牌中的默认 DACL 只允许访问由访问令牌表示的用户。 |
nLength | 此结构的大小(以字节为单位)。 将此值设置为此结构的大小。 |
创建进程
STARTUPINFO si;
PROCESS_INFORMATION pi ={0};
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWrite; //新创建进程的错误信息连在写管道一端
si.hStdOutput = hWrite; //新创建进程的标准输出连在写管道一端
si.wShowWindow = SW_HIDE; //隐藏窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (!CreateProcess(NULL, pCommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))//创建子进程
{
if (pCommandLine)
delete pCommandLine;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
return 1;
}
以上的做法有个问题,就是界面会一直卡在这里
解决办法:
在主线程中开一个线程(线程1):创建子进程
在线程1中再开一个线程读取日志返回到界面