欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用CreateProcess进行调用exe,实现重定向

程序员文章站 2022-05-12 21:30:46
...
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<stdio.h>

#include <iostream>
#include<stdio.h>
#include <string.h>
#include<windows.h>
#include<thread>
#include<mutex>


/* 重定向到文件&标准输出*/
int main1()
{
#if 0 /* 重定向到文件*/
	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	HANDLE h = CreateFile((L"output.log"),
		FILE_APPEND_DATA,
		FILE_SHARE_WRITE | FILE_SHARE_READ,
		&sa,
		OPEN_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
#else //重定向到标准输出
	HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
#endif
	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	BOOL ret = FALSE;
	DWORD flags = CREATE_NO_WINDOW;

	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags |= STARTF_USESTDHANDLES;
	si.wShowWindow = SW_HIDE;;
	si.hStdInput = NULL;
	si.hStdError = h;
	si.hStdOutput = h;

	WCHAR exename[MAX_PATH];
	WCHAR cmdLine[MAX_PATH];


	wsprintf(exename, L"D:\\jobWork\\2021\\las提高程点\\bin\\x64\\LasExtractGeight.exe");
	wsprintf(cmdLine, L"D:\\jobWork\\2021\\las提高程点\\bin\\x64\\LasExtractGeight.exe ");

	//CREATE_NO_WINDOW
	//CREATE_NEW_CONSOLE
	ret = CreateProcess(exename, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
	if (ret)
	{
		WaitForSingleObject(pi.hProcess, INFINITE);
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		CloseHandle(h);
		return 0;
	}
	//关闭文件
	CloseHandle(h);
	return -1;

}

struct treadfunData{
	HANDLE hReadPipe;
	bool stop = 0;
	std::mutex mutex;

	bool isStop() {
		bool b = 0;
		if (mutex.try_lock())	{
			b = stop;
			mutex.unlock();
		}
		return b;
	}
	void setStop() {
		if (mutex.try_lock()) {
			stop = 1;
			mutex.unlock();
		}
	}
};

void treadfun(treadfunData* data) {
	if (!data) return;
	BOOL bRet = FALSE;
	DWORD dwRead = 0;
	DWORD dwAvail = 0;
	char cbBuf[4096] = { 0 };
	do
	{
		if (data->isStop()) return;
		std::cout << "test.." << std::endl;
		//PeekNamePipe用来预览一个管道中的数据,用来判断管道中是否为空
		if (!PeekNamedPipe(data->hReadPipe, NULL, NULL, &dwRead, &dwAvail, NULL) || dwAvail <= 0)	{
			continue;
		}
		//这里是读管道,即便已经没有数据,仍然会等待接收数据,因为,子进程会认为父进程仍有数据要发送,只是暂时没法送,
		//所以,会“卡”在这里。所以才需要PeekNamePipe
		if (ReadFile(data->hReadPipe, cbBuf, 128, &dwRead, NULL))		{
			if (dwRead == 0) 	continue;
			std::cout << dwRead << std::endl;
			std::cout << cbBuf << std::endl;
		}
	} while (TRUE);
}

/* 重定向到管道*/
int main()
{
	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa);
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = NULL;

	HANDLE hReadPipe = NULL;
	HANDLE hWritePipe = NULL;
	CreatePipe(&hReadPipe, &hWritePipe, &sa, 0);

	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	BOOL ret = FALSE;
	DWORD flags = CREATE_NO_WINDOW;

	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags |= STARTF_USESTDHANDLES;
	si.wShowWindow = SW_HIDE;;
	si.hStdInput = NULL;
	si.hStdError = hWritePipe;
	si.hStdOutput = hWritePipe;

	WCHAR exename[MAX_PATH];
	WCHAR cmdLine[MAX_PATH];


	wsprintf(exename, L"D:\\jobWork\\2021\\las提高程点\\bin\\x64\\LasExtractGeight.exe");
	wsprintf(cmdLine, L"D:\\jobWork\\2021\\las提高程点\\bin\\x64\\LasExtractGeight.exe ");

	//CREATE_NO_WINDOW
	//CREATE_NEW_CONSOLE
	ret = CreateProcess(exename, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
	if (ret)
	{
		treadfunData treadfunData_;
		treadfunData_.hReadPipe = hReadPipe;
		std::thread  thread_(treadfun, &treadfunData_);
				
		WaitForSingleObject(pi.hProcess, INFINITE);
		treadfunData_.setStop();
		thread_.join();
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		CloseHandle(hWritePipe);
		CloseHandle(hReadPipe);

		return 0;
	}
	//关闭文件
	CloseHandle(hWritePipe);
	CloseHandle(hReadPipe);
	return -1;

}