1. 程式人生 > >C++實現重定向命令以及管道命令

C++實現重定向命令以及管道命令

// >命令

char* Get_Char(char **command,int count) {
	int len = Get_Count(command[count - 1]);
	char *wth = new char[len + 1];
	for (int i = 0; i < len; i++) {
		wth[i] = command[count - 1][i];
	}
	wth[len] = '\0';
	return wth;
}

DWORD Get_Actuall(char *p) {  //獲得緩衝區資料實際的大小
	int i = 0;
	while (p[i] != '\0') {
		i++;
	}
	return i;
}

wchar_t *char2LPCTSTR(char **command, int count) {

	int len = Get_Count(command[count - 1]);
	wchar_t *wth = new wchar_t[len + 1];
	for (int i = 0; i < len; i++) {
		wth[i] = command[count - 1][i];
	}
	wth[len] = '\0';
	return wth;
}

wchar_t *char2LPCTSTR(char *p) {  //將char *轉換為wchar_t

	int len = Get_Count(p);
	wchar_t *wth = new wchar_t[len + 1];
	for (int i = 0; i < len; i++) {
		wth[i] = p[i];
	}
	wth[len] = '\0';
	return wth;
}

TCHAR *char2TCHAR(char **command, int count) {

	int len = Get_Count(command[count - 1]);
	TCHAR *wth = new TCHAR[len + 1];
	for (int i = 0; i < len; i++) {
		wth[i] = command[count - 1][i];
	}
	wth[len] = '\0';
	return wth;
}
// >

void Redirection_1(char **&command,int count) {
	wchar_t *path = char2LPCTSTR(command,count);
	LPCTSTR  outputFile = path;
	SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
	HANDLE hFile = CreateFile(
		outputFile,
		GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		&sa,
		TRUNCATE_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hFile == INVALID_HANDLE_VALUE) {
		//int err = GetLastError();
		return;
	}

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	si.wShowWindow = SW_HIDE; //不顯示建立的程序的視窗
	si.hStdOutput = hFile;//重定向輸出控制代碼為之前建立的檔案控制代碼
	TCHAR *cmdline = char2TCHAR(command,1);
	//SetFilePointer(hFile, 0, NULL, FILE_END);  
	if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
		//等待開啟的程序結束並關閉相關控制代碼
		WaitForSingleObject(pi.hProcess, INFINITE);
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
	} else {
		int err = GetLastError();
	}
	//關閉檔案控制代碼
	CloseHandle(hFile);

}

// >>命令
void Redirection_2(char **&command, int count) {
	wchar_t *path = char2LPCTSTR(command, count);
	LPCTSTR  outputFile = path;
	SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
	HANDLE hFile = CreateFile(
		outputFile,
		GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		&sa,
		OPEN_ALWAYS /*| TRUNCATE_EXISTING*/,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hFile == INVALID_HANDLE_VALUE) {
		//int err = GetLastError();
		return;
	}

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	si.wShowWindow = SW_HIDE; //不顯示建立的程序的視窗
	si.hStdOutput = hFile;//重定向輸出控制代碼為之前建立的檔案控制代碼
	TCHAR *cmdline = char2TCHAR(command, 1);
	SetFilePointer(hFile, 0, NULL, FILE_END);  //定位到檔案尾部
	if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
		//等待開啟的程序結束並關閉相關控制代碼
		WaitForSingleObject(pi.hProcess, INFINITE);
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
	}
	else {
		int err = GetLastError();
	}
	//關閉檔案控制代碼
	CloseHandle(hFile);
}

// <命令
void Redirection_3(char **&command, int count) {
	wchar_t *path = char2LPCTSTR(command, count);
	LPCTSTR  inputFile = path;
	SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
	HANDLE hFile = CreateFile(
		inputFile,
		GENERIC_READ,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		&sa,
		OPEN_ALWAYS /*| TRUNCATE_EXISTING*/,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hFile == INVALID_HANDLE_VALUE) {
		//int err = GetLastError();
		return;
	}

	//以下是為了驗證讀取的正確性
	char *p = "temp.txt";
	wchar_t *path1 = char2LPCTSTR(p);
	LPCTSTR  outputFile = path1;
	HANDLE hOutput = CreateFile(
		outputFile, 
		GENERIC_WRITE, 
		0, 
		&sa, 
		CREATE_ALWAYS, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL);
	if (hOutput == INVALID_HANDLE_VALUE) {
		return;
	}
	//以上是為了驗證讀取的正確性

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;;
	si.wShowWindow = SW_HIDE; //不顯示建立的程序的視窗
	si.hStdInput = hFile;//重定向輸入控制代碼為之前建立的檔案控制代碼
	si.hStdOutput = hOutput; //重定向輸出控制代碼為之前建立的檔案控制代碼
	TCHAR *cmdline = char2TCHAR(command, 1);
	if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
		//等待開啟的程序結束並關閉相關控制代碼
		WaitForSingleObject(pi.hProcess, INFINITE);
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
	}
	else {
		int err = GetLastError();
	}
	//關閉檔案控制代碼
	CloseHandle(hFile);
	CloseHandle(hOutput);
}

// <<命令
void Redirection_4(char **&command, int count) {
	
	HANDLE hRead = NULL;
	HANDLE hWrite = NULL;

	SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
	// 新建立的程序繼承管道讀寫控制代碼
	if (FALSE == CreatePipe(&hRead, &hWrite, &sa, 0)) {
		return;
	}

	if (NULL == hRead || NULL == hWrite) {
		return;
	}
	char *buf = Get_Char(command,count);
	DWORD dwWrite;
	WriteFile(hWrite, buf, Get_Actuall(buf), &dwWrite, NULL); //將資料寫入管道的輸入端
	CloseHandle(hWrite);
	//建立程序,從管道輸出端讀取資料

	//以下是為了驗證讀取的正確性
	char *p = "temp.txt";
	wchar_t *path1 = char2LPCTSTR(p);
	LPCTSTR  outputFile = path1;
	HANDLE hOutput = CreateFile(
		outputFile,
		GENERIC_WRITE,
		0,
		&sa,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hOutput == INVALID_HANDLE_VALUE) {
		return;
	}
	//以下是為了驗證讀取的正確性

	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;;
	si.wShowWindow = SW_HIDE; //不顯示建立的程序的視窗
	si.hStdInput = hRead;//重定向輸入控制代碼為之前建立的管道讀出控制代碼
	si.hStdOutput = hOutput; //重定向輸出控制代碼為之前建立的檔案控制代碼
	TCHAR *cmdline = char2TCHAR(command, 1);
	if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
		//等待開啟的程序結束並關閉相關控制代碼
		WaitForSingleObject(pi.hProcess, INFINITE);
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
	}
	else {
		int err = GetLastError();
	}
	
	//關閉管道讀寫控制代碼
	CloseHandle(hRead);
	CloseHandle(hOutput);

}

// |命令
void Redirection_5(char **&command, int count) {  //這裡利用檔案讀寫
	//const char *path1 = Get_Char(command, count);
	//const char *path2 = Get_Char(command, 1);

	HANDLE hRead = NULL;
	HANDLE hWrite = NULL;

	SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE }; 
	// 新建立的程序繼承管道讀寫控制代碼
	if (FALSE == CreatePipe(&hRead, &hWrite, &sa, 0)) {
		return;
	}

	if (NULL == hRead || NULL == hWrite) {
		return;
	}
	
	//建立程序,從管道輸出端讀取資料

	//以下是為了驗證讀取的正確性
	char *p = "temp.txt";
	wchar_t *path1 = char2LPCTSTR(p);
	LPCTSTR  outputFile = path1;
	HANDLE hOutput = CreateFile(
		outputFile,
		GENERIC_WRITE,
		0,
		&sa,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hOutput == INVALID_HANDLE_VALUE) {
		return;
	}
	//以上是為了驗證讀取的正確性

	//輸出程序,輸出定位到管道的輸入端
	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi = { 0 };
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	si.wShowWindow = SW_HIDE; //不顯示建立的程序的視窗
	//si.hStdInput = hRead;//重定向輸入控制代碼為之前建立的管道讀出控制代碼
	si.hStdOutput = hWrite; //重定向輸出控制代碼為之前建立的管道輸入控制代碼
	TCHAR *cmdline = char2TCHAR(command, 1);
	if (CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
		//等待開啟的程序結束並關閉相關控制代碼
		WaitForSingleObject(pi.hProcess, INFINITE);
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
	}
	else {
		int err = GetLastError();
	}
	CloseHandle(hWrite); //關閉管道輸入控制代碼

	//輸入程序,輸入定位到管道的輸出端
	STARTUPINFO si1 = { sizeof(si1) };
	PROCESS_INFORMATION pi1 = { 0 };
	si1.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	si1.wShowWindow = SW_HIDE; //不顯示建立的程序的視窗
	si1.hStdInput = hRead;//重定向輸入控制代碼為之前建立的管道讀出控制代碼
	si1.hStdOutput = hOutput; //重定向輸出控制代碼為之前建立的管道輸入控制代碼
	TCHAR *cmdline1 = char2TCHAR(command, count);
	if (CreateProcess(NULL, cmdline1, NULL, NULL, TRUE, NULL, NULL, NULL, &si1, &pi1)) {
		//等待開啟的程序結束並關閉相關控制代碼
		WaitForSingleObject(pi1.hProcess, INFINITE);
		::CloseHandle(pi1.hThread);
		::CloseHandle(pi1.hProcess);
	}
	else {
		int err = GetLastError();
	}

	//關閉管道讀控制代碼
	CloseHandle(hRead);
	CloseHandle(hOutput); //關閉檔案控制代碼
}