天天看點

使用CreateProcess進行調用exe,實作重定向

// 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;

}


           

繼續閱讀