Click here to Skip to main content
15,886,782 members
Articles / Programming Languages / C++

Useful Managers

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
11 Aug 2001 80.4K   1.2K   16  
An add-in for Devstudio that provides tag indexing and search, window, bookmarks, session and other managers
// Run.cpp : implementation file
//

#include "StdAfx.h"
#include <aFXWIN.H>
#include "run.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// Run

Run::Run()
{
	m_dwProcessId = DWORD(-1);
	m_pReadThread = NULL;
	m_pReadThread2 = NULL;

	m_hChildStdinRd = NULL;
	m_hChildStdinWr = NULL;
	m_hChildStdinWrDup = NULL;
	m_hChildStdoutRd = NULL;
	m_hChildStdoutWr = NULL;
	m_hChildStdoutRdDup = NULL;
	m_hChildErrorRd = NULL;
	m_hChildErrorWr = NULL;
	m_hChildErrorRdDup = NULL;
  
  params[0] = params[1] = NULL;
}
                                        
Run::~Run()
{
}

/////////////////////////////////////////////////////////////////////////////
// Run message handlers

#define BUFSIZE 1024*32

BOOL Run::CreateShellRedirect()
{
	SECURITY_ATTRIBUTES saAttr;
	BOOL bSuccess;

	// Set the bInheritHandle flag so pipe handles are inherited.
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
	saAttr.bInheritHandle = TRUE;
	saAttr.lpSecurityDescriptor = NULL;

	// The steps for redirecting child process's STDOUT: 
	//	 1. Save current STDOUT, to be restored later. 
	//	 2. Create anonymous pipe to be STDOUT for child process. 
	//	 3. Set STDOUT of the parent process to be write handle to 
	//		the pipe, so it is inherited by the child process. 
	//	 4. Create a noninheritable duplicate of the read handle and
	//		close the inheritable read handle.  
	
	// Save the handle to the current STDOUT.  
	HANDLE hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);  
	
	// Create a pipe for the child process's STDOUT.  
	if (!CreatePipe(&m_hChildStdoutRd, &m_hChildStdoutWr, &saAttr, 0))
	{
		TRACE0(_T("Stdout pipe creation failed\n"));
		return FALSE;
	}

	// Set a write handle to the pipe to be STDOUT.  
	if (!SetStdHandle(STD_OUTPUT_HANDLE, m_hChildStdoutWr))
	{
		TRACE0(_T("Redirecting STDOUT failed\n"));
		return FALSE;
	}
   
	// Create noninheritable read handle and close the inheritable read handle. 
	bSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildStdoutRd, 
		GetCurrentProcess(), &m_hChildStdoutRdDup, 
		0, FALSE, 
		DUPLICATE_SAME_ACCESS);
	if (!bSuccess)
	{
		TRACE0(_T("DuplicateHandle failed\n"));
		return FALSE;
	}
	CloseHandle(m_hChildStdoutRd);

	// The steps for redirecting child process's ERROR: 
	//	 1. Save current ERROR, to be restored later. 
	//	 2. Create anonymous pipe to be ERROR for child process. 
	//	 3. Set ERROR of the parent process to be write handle to 
	//		the pipe, so it is inherited by the child process. 
	//	 4. Create a noninheritable duplicate of the read handle and
	//		close the inheritable read handle.  

  // Save the handle to the current ERROR.  
	HANDLE hSaveError = GetStdHandle(STD_ERROR_HANDLE);  
	
	// Create a pipe for the child process's ERROR.  
	if (!CreatePipe(&m_hChildErrorRd, &m_hChildErrorWr, &saAttr, 0))
	{
		TRACE0(_T("Error pipe creation failed\n"));
		return FALSE;
	}

	// Set a write handle to the pipe to be ERROR.  
	if (!SetStdHandle(STD_ERROR_HANDLE, m_hChildErrorWr))
	{
		TRACE0(_T("Redirecting ERROR failed\n"));
		return FALSE;
	}
   
	// Create noninheritable read handle and close the inheritable read handle. 
	bSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildErrorRd, 
		GetCurrentProcess(), &m_hChildErrorRdDup, 
		0, FALSE, 
		DUPLICATE_SAME_ACCESS);
	if (!bSuccess)
	{
		TRACE0(_T("DuplicateHandle failed\n"));
		return FALSE;
	}
	CloseHandle(m_hChildErrorRd);



	
	// The steps for redirecting child process's STDIN: 
	//	 1.  Save current STDIN, to be restored later. 
	//	 2.  Create anonymous pipe to be STDIN for child process. 
	//	 3.  Set STDIN of the parent to be the read handle to the 
	//		 pipe, so it is inherited by the child process. 
	//	 4.  Create a noninheritable duplicate of the write handle, 
	//		 and close the inheritable write handle.  

	// Save the handle to the current STDIN. 
	HANDLE hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);  

	// Create a pipe for the child process's STDIN.  
	if (!CreatePipe(&m_hChildStdinRd, &m_hChildStdinWr, &saAttr, 0))
	{
		TRACE0(_T("Stdin pipe creation failed\n"));
		return FALSE;
	}
	// Set a read handle to the pipe to be STDIN.  
	if (!SetStdHandle(STD_INPUT_HANDLE, m_hChildStdinRd)) 
	{
		TRACE0(_T("Redirecting Stdin failed\n"));
		return FALSE;
	}
	// Duplicate the write handle to the pipe so it is not inherited.  
	bSuccess = DuplicateHandle(GetCurrentProcess(), m_hChildStdinWr, 
		GetCurrentProcess(), &m_hChildStdinWrDup, 
		0, FALSE, 				  // not inherited	   
		DUPLICATE_SAME_ACCESS); 
	if (!bSuccess) 
	{
		TRACE0(_T("DuplicateHandle failed\n"));
		return FALSE;
	}
	CloseHandle(m_hChildStdinWr);  
	
	// Now create the child process. 
	if (!CreateChildProcess())
	{
		TRACE0(_T("CreateChildProcess failed\n"));
		return FALSE;
	}
	// After process creation, restore the saved STDIN and STDOUT.  
	if (!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
	{
		TRACE0(_T("Re-redirecting Stdin failed\n"));
		return FALSE;
	}
	if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
	{
		TRACE0(_T("Re-redirecting Stdout failed\n"));
		return FALSE;
	}
	
  delete params[0];  delete params[1];

  MakeParams();

  m_pReadThread = AfxBeginThread((AFX_THREADPROC)ReadPipeThreadProc, (LPVOID)(params[0]));
	if (!m_pReadThread)
	{
		TRACE0(_T("Cannot start read-redirect thread!\n"));
		return FALSE;
	}
	m_pReadThread2 = AfxBeginThread((AFX_THREADPROC)ReadPipeThreadProc, (LPVOID)(params[1]));
	if (!m_pReadThread2)     
	{
		TRACE0(_T("Cannot start read2-redirect thread!\n"));
		return FALSE;
	}
	return TRUE;
}

BOOL Run::CreateChildProcess()
{
	PROCESS_INFORMATION piProcInfo;
	STARTUPINFO siStartInfo;  

	// Set up members of STARTUPINFO structure.  
	ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
	siStartInfo.cb = sizeof(STARTUPINFO);  
	
	siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	siStartInfo.wShowWindow = SW_HIDE;
	siStartInfo.hStdInput = m_hChildStdinRd;
	siStartInfo.hStdOutput = m_hChildStdoutWr;
	siStartInfo.hStdError = m_hChildErrorWr;

	TCHAR shellCmd[_MAX_PATH];
	if (!GetEnvironmentVariable(_T("ComSpec"), shellCmd, _MAX_PATH))
		  return FALSE;
#ifdef _UNICODE
	_tcscat(shellCmd, _T(" /U"));
#else	
	_tcscat(shellCmd, _T(" /A"));
#endif 
	// Create the child process.  
	BOOL bRet = CreateProcess(NULL, 
			shellCmd, 	   // applicatin name
			NULL, 		  // process security attributes 
			NULL, 		  // primary thread security attributes 
			TRUE, 		  // handles are inherited 
			CREATE_NEW_CONSOLE, // creation flags 
			NULL, 		  // use parent's environment 
			NULL, 		  // use parent's current directory 
			&siStartInfo,  // STARTUPINFO pointer 
			&piProcInfo);  // receives PROCESS_INFORMATION 
	if (bRet)
		m_dwProcessId = piProcInfo.dwProcessId;
	return bRet;
}

void Run::WriteToPipe(LPCTSTR line, bool files)
{
  if(files)
  {
    params[0]->open("log.txt");
    params[1]->open("errlog.txt");
  }

	DWORD dwWritten;
	if(!WriteFile(m_hChildStdinWrDup, line, _tcslen(line)*sizeof(TCHAR), 
			&dwWritten, NULL))
   AfxMessageBox("Error");
}

UINT Run::ReadPipeThreadProc(LPVOID pParam)
{
	DWORD dwRead;
	TCHAR chBuf[BUFSIZE]; 
	RunParams* params = (RunParams*)pParam;

	TRACE0(_T("ReadPipe Thread begin run\n"));
  memset(chBuf,'1',BUFSIZE);
	for(;;)	
	{ 
    if (!ReadFile(params->handle, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0) 
    {
      AfxMessageBox("Error");
			break; 
    } 
		chBuf[dwRead/sizeof(TCHAR)] = _T('\0');
		params->addText(chBuf);
	} 
	return 1;
}

void Run::OnDestroy() 
{
	if (m_dwProcessId != DWORD(-1))
	{
		HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId);
		if (hProcess)
    {                                                       
			TerminateProcess(hProcess, 0);
                                        
			WriteToPipe(_T("exit\r\n"),false);
			//WaitForSingleObject(hProcess, INFINITE);
			WaitForSingleObject(hProcess, 2000);

			CloseHandle(hProcess);
		}
	}
	if (m_pReadThread)
	{
		TerminateThread(m_pReadThread->m_hThread, 0);
		delete m_pReadThread;
		m_pReadThread = NULL;
	}
	if (m_pReadThread2)
	{
		TerminateThread(m_pReadThread2->m_hThread, 0);
		delete m_pReadThread2;
		m_pReadThread2 = NULL;
	}

  CloseHandle(m_hChildStdinRd);
	CloseHandle(m_hChildStdoutWr);
	CloseHandle(m_hChildErrorWr);
	CloseHandle(m_hChildStdinWrDup);
	CloseHandle(m_hChildStdoutRdDup);
	CloseHandle(m_hChildErrorRdDup);
	m_dwProcessId  = DWORD(-1);
  delete params[0];  delete params[1];
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Russian Federation Russian Federation
Mike has been programming in C/C++ for 11 years and Visual C++/MFC for 4 years. His background includes pure and applied mathematics, engineering and physics, and he is currently based in Moscow, Russia.

Comments and Discussions