[Windows]_[初级]_[创建独立子进程和读取子进程的输出]


场景:

1.  有一些外部工具命令需要通过程序调用,比如启动服务器或者使用网络命令获取输出。

2.  使用了匿名管道CreatePipe获取子进程输出.


参考:

1.  MSDN的主题《Creating a Child Process with Redirected Input and Output》。

2.  《Windows核心编程》进程章节.


代码:

#include "test_shellrun.h"
#include <stdlib.h>
#include <stdint.h>
#include <iostream>
#include <Windows.h>
using namespace std;

bool ExecuteCommandNoWait(const wchar_t* command)
{
	STARTUPINFOW startupInfo = {sizeof(STARTUPINFOW)};
	GetStartupInfoW(&startupInfo);
	startupInfo.dwFlags=0;
	startupInfo.wShowWindow=SW_HIDE;

	bool ret = true;
	PROCESS_INFORMATION  info;
	wchar_t* wlpcmd = wcsdup(command);
	if (CreateProcessW(NULL , wlpcmd , NULL , NULL , TRUE , CREATE_NO_WINDOW, NULL
		, NULL	, &startupInfo, &info))
	{
		CloseHandle(info.hProcess);
		CloseHandle(info.hThread);
	}else
	{
		 ret = false; 
	}
	free(wlpcmd);
	return ret;
}

std::string ExecuteCommandAndWait(const wchar_t* command,uint32_t wait_millisecond)
{
	SECURITY_ATTRIBUTES sa;
	HANDLE hChildStdoutRd,hChildStdoutWr;

	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	std::string buf;
	if (!CreatePipe(&hChildStdoutRd,&hChildStdoutWr,&sa,0))
	{
		return buf;
	}

	if (!SetHandleInformation(hChildStdoutRd, HANDLE_FLAG_INHERIT, 0))
	{
		CloseHandle(hChildStdoutWr);
		CloseHandle(hChildStdoutRd);
		return buf;
	}

	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );

	ZeroMemory( &si, sizeof(STARTUPINFO) );
	si.cb = sizeof(STARTUPINFO); 
	si.hStdError = hChildStdoutWr;
	si.hStdOutput = hChildStdoutWr;
	si.dwFlags |= STARTF_USESTDHANDLES;

	wchar_t* wlpcmd = wcsdup(command);
	//CREATE_UNICODE_ENVIRONMENT
	if (!CreateProcessW(NULL, wlpcmd,NULL,NULL,TRUE,0 ,NULL,NULL,&si,&pi))
	{    
		CloseHandle(hChildStdoutWr);
		CloseHandle(hChildStdoutRd);
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		free(wlpcmd);
		return buf;
	}

	WaitForSingleObject(pi.hProcess,wait_millisecond);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	CloseHandle(hChildStdoutWr);

	char buffer[1024] = {0};
	DWORD bytesRead;

	BOOL ret = false;

	while (true)
	{
		ret = ReadFile(hChildStdoutRd,buffer,1024,&bytesRead,NULL);
		if (!ret || bytesRead == 0)
		{
			break;
		}
		buf.append(buffer,bytesRead);
	}

	CloseHandle(hChildStdoutRd);
	free(wlpcmd);
	return buf;
}


 调用: 
 

ExecuteCommandNoWait(L"notepad.exe");
std::string output = ExecuteCommandAndWait(L"ping www.baidu.com",-1);
cout << "output: " << output << endl;

注意:ReadFile在读取孙子进程的输出时,就是子进程又创建了子进程,会卡住,这个问题暂时用一个线程定时器调用:

CancelIoEx

关闭ReadFile,目前没有更好的办法,有谁知道的留了言.





你可能感兴趣的:(windows,输出,readfile,子进程,CreatePipe)