Click here to Skip to main content
Click here to Skip to main content

Execute a Console Application From VC++

By , 16 Apr 2005
 

Introduction

To Execute a Console Application From VC++ and retrieve the messages shown in the console.

In many situations we may need to execute a console application or a DOS application from within our MFC application. ShellExcecute can be used for this purpose, but can only be used to run the application. Messages shown in the console is not reachable. In such cases the following procedure can help.

Here we create a read write pipe (two separate pipes, one for reading and one for writing).

Then we use CreateProcess to execute the process. Createprocess must be supplied with pointers to variables of STARTUPINFO and PROCESS_INFORMATION structures.

The pipes created are assigned to STARTUPINFO structure before it is passed to the CreateProcess function.

The CreateProcess function is used to run a new program.

CreateProcess( 
        LPCWSTR lpszImageName, 
        LPCWSTR lpszCmdLine, 
        LPSECURITY_ATTRIBUTES lpsaProcess, 
        LPSECURITY_ATTRIBUTES lpsaThread, 
        BOOL fInheritHandles, 
        DWORD fdwCreate, 
        LPVOID lpvEnvironment, 
        LPWSTR lpszCurDir, 
        LPSTARTUPINFOW lpsiStartInfo, 
        LPPROCESS_INFORMATION lppiProcInfo);
  • lpszImageName

    Pointer to a null-terminated string that specifies the module to execute.

  • lpszCmdLine

    Pointer to a null-terminated string that specifies the command line to execute. The system adds a null character to the command line, trimming the string if necessary, to indicate which file was actually used.

The function ExecuteExternalFile, takes two arguments:

  1. the application to be executed.
  2. the arguments.

It executes the application and returns the messages that are printed into the console as a CString.

CString ExecuteExternalFile(CString csExeName, CString csArguments)
{
  CString csExecute;
  csExecute=csExeName + " " + csArguments;
  
  SECURITY_ATTRIBUTES secattr; 
  ZeroMemory(&secattr,sizeof(secattr));
  secattr.nLength = sizeof(secattr);
  secattr.bInheritHandle = TRUE;

  HANDLE rPipe, wPipe;

  //Create pipes to write and read data
  CreatePipe(&rPipe,&wPipe,&secattr,0);
  //
  STARTUPINFO sInfo; 
  ZeroMemory(&sInfo,sizeof(sInfo));
  PROCESS_INFORMATION pInfo; 
  ZeroMemory(&pInfo,sizeof(pInfo));
  sInfo.cb=sizeof(sInfo);
  sInfo.dwFlags=STARTF_USESTDHANDLES;
  sInfo.hStdInput=NULL; 
  sInfo.hStdOutput=wPipe; 
  sInfo.hStdError=wPipe;
  char command[1024]; strcpy(command,  
          csExecute.GetBuffer(csExecute.GetLength()));

  //Create the process here.
  CreateProcess(0 command,0,0,TRUE,
          NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
  CloseHandle(wPipe);

  //now read the output pipe here.
  char buf[100];
  DWORD reDword; 
  CString m_csOutput,csTemp;
  BOOL res;
  do
  {
                  res=::ReadFile(rPipe,buf,100,&reDword,0);
                  csTemp=buf;
                  m_csOutput+=csTemp.Left(reDword);
  }while(res);
  return m_csOutput;
}

Hope this code will be useful for you.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Smith_TVPM
Software Developer
India India
Member
Software Engineer,
Technopark, Kerala.
 
Rx 135 Owner
Yamaha Fan.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionsome time ReadFile not respondingmemberLe@rner15 Apr '13 - 1:53 
hi ,
 
this is such a nice explanation,
 
I use it ,but I have a problem sometime ReadFile not responding,
 
how can I add timout feature here,
 

thanks.
GeneralMissing calls to CloseHandle, causes memory leakmemberMember 15897532 May '11 - 4:42 
The following lines should be added after the call to GetExitCodeProcess: CloseHandle(pInfo.hThread);
CloseHandle(pInfo.hProcess);
GeneralI found another method, by searching in msdn....memberSteppenwolf19 Jan '11 - 21:48 
int ExecuteExternalFile(LPTSTR szExeName, LPTSTR szArguments)
{
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
 
	ZeroMemory( &si, sizeof(si) );
	si.cb = sizeof(si);
	ZeroMemory( &pi, sizeof(pi) );
 
	TCHAR szNameArg[1024];
	strcpy(szNameArg, szExeName);
	strcat(szNameArg, " ");
	strcat(szNameArg, szArguments);
 
	// Start the child process. 
	if( !CreateProcess( NULL,   // No module name (use command line)
		szNameArg,      // Command line
		NULL,           // Process handle not inheritable
		NULL,           // Thread handle not inheritable
		FALSE,          // Set handle inheritance to FALSE
		0,              // No creation flags
		NULL,           // Use parent's environment block
		NULL,           // Use parent's starting directory 
		&si,            // Pointer to STARTUPINFO structure
		&pi )           // Pointer to PROCESS_INFORMATION structure
		) 
	{
		printf( "CreateProcess failed (%d).\n", GetLastError() );
		return 1;
	}
 
	// Wait until child process exits.
	WaitForSingleObject( pi.hProcess, INFINITE );
 
	// Close process and thread handles. 
	CloseHandle( pi.hProcess );
	CloseHandle( pi.hThread );
 
	return 0;
}

GeneralMy vote of 2memberSteppenwolf19 Jan '11 - 21:43 
it's so complicated
QuestionAdd write functionalitymemberMarco Fiaschi2 Aug '10 - 8:07 
I'm using your code instead of _popen() function without problems to read from the console...
but I need to write data on the console like the _popen()/fputs() functions do.
Is possible to add this functionality to your code? If yes, how?
 
Thanks!
Marco
GeneralProblem with bufferingmembertoschu7220 Nov '08 - 1:37 
Hi! The code is great for me, too. I have just one problem:
 
As if I have to process the returned text immediately for me the problem is that there is a buffer in the pipe handled by the OS. Does anybody know how to tell the pipe that all bytes have to be put out immediately, so turn off the buffer? If I set the ReadFile buffer and also the CreatePipe buffer to 1 it doesn't help; it looks like the pipe collects bytes until the internal buffer (1KB?) is full and then sends out all together.
 
Thanks,
Tobias
GeneralParser 2membersuhi22 Apr '08 - 3:37 
Hi All,
 

I have to parse a text file that is of the size 2KB mb. I want to do this in MFC.
 
I want to know what is the maximum size of a file that could be parsed with MFC. Like for example can i parse a txt file whose size is >20 mb Will that be a hit on the perfomance?
 
I hope the scenario what I am presenting is clear.
 
So guys can you throw some light on this and pleeeease do let me know at the earliest.
 
Thanks a lot in advance.
 
Suhi
GeneralParsermembersuhi22 Apr '08 - 3:22 
Hi All,
I am new to MFC.
Can anyone provide me the sample code in MFC for writing parser for
text file.
 
Regards
Suhi
QuestionHow to receive numeric resultsmembersmzhaq26 Sep '07 - 18:10 
Dear. Thank you very much for sharing such usefull information. The code you gave recieves characters from console.
 
I have one question. I run 1 console program from my MFC application. The console program writes to console the results which are double precision floating values but are psesented to console as ASCII strings. Further if I attempt to read data before there is some data available, newline characters are received. Can you please help me how to receive the numeric results of that program into my MFC application?
 
Thank you very much.
AnswerRe: How to receive numeric resultsmemberEvan Lin4 Sep '08 - 16:06 
how about using strtok and atoi ?
QuestionPossible with MFC applicationmemberkazim bhai30 Aug '07 - 2:00 
Is it possible to execute an MFC application in another MFC application with this code?
 
It is Kazim

GeneralNice one. Thanksmemberhungrytom27 Aug '07 - 23:59 
Simple and succinct!
 
Nice one. This answers a lot of questions for me.
 
Cheers
QuestionGreat job, but seem not compatible with unicode ?memberOlivier Booklage22 Feb '07 - 9:57 
Hello,
I use your nice function since lot of time and for the first time I must use it in unicode program:
 
char command[1024]; strcpy(command,
csExecute.GetBuffer(csExecute.GetLength()));
 
->
 
TCHAR command[1024];
_tcscpy(command,csExecute.GetBuffer(csExecute.GetLength()));
 
First, the output CString is truncate ( I call svn.exe info from SubVersion package ) and lot of accents are wrong. So my first question is why the output string seem to be truncate and why we have strange accents characters ( maybe the loop ReadFile(rPipe,buf,1023,&reDword,0); built only a multibyte CString ? )
 
Thank for your help,
 
@livier.
AnswerRe: Great job, but seem not compatible with unicode ?memberOlivier Booklage22 Feb '07 - 20:57 
Problems with characters solved by
 
::OemToChar(buf, translated);
csTemp=translated;
 
but output truncated not solved yet..
 
@livier.

GeneralGreat! Keep it upmemberrm_pkt7 Feb '07 - 19:29 
Hi Smith_TVPM
Simple and good job.
Thanks for Posting it.
 
Smile | :) Smile | :) Smile | :)
 
rm-Pkt
Generalcoolmemberzoz18 Jan '07 - 10:44 
Thank you very much for the code, it works fine.
I give you just a 5 Big Grin | :-D
 
best regards
GeneralCool n Nice implementationmemberrassg17 Jan '07 - 18:36 
Excellent idea..ther..Thanks for sharing the same.
QuestionCan we keep the output in the console as well?memberc.sunita3 Jan '07 - 7:58 
Is there a way to keep the output in the console windosw, and also use the pipes?
GeneralCool!memberSteve_pqr14 Dec '06 - 9:00 
Great - worked first time, just what I needed, thanks
Generalexcellentmemberstephen(china)12 Oct '06 - 19:42 
thank you
GeneralExcellent article-just what I wantedmemberdba3 Sep '06 - 23:16 
I have been searching for ages for a method of retrieving data directly into a string variable. Up until now I have had to redirect the output to a file and subsequently open the file to read in the data, that works but it is too clumsy and inefficient.
 
Although I've seen other good articles posted on this subject they have concentrated on bringing the data into a control which was not what I was really looking for. This is so easy and straightforward.
 
Many thanks!
Generalsystem callmemberhimakiran25 Aug '06 - 11:42 
i was faced with the same problem of running a dos appln from within vc++. but instead of using lengthy code ie CreateProcess() and ShellExecute(), i made do with a onliner system call
 
system(const char*);
the only problem i am encounetring with this is that the command prompt window appears briefly when the external appln runs.
 

 
HIMAKIRAN KUMAR

QuestionProcess waiting answermemberRickyC10 Apr '06 - 1:42 
Hello!
Thanks for the article Smile | :)
But I have a doubt, could you give me some help?
I have a process that executes and needs some answers to continue the execution. I try to use the write handle, but I have no sucess. Does have a easy way to complement that in your current code?
 
Thanks again!
cheers!
 
-- modified at 10:05 Monday 10th April, 2006
AnswerRe: Process waiting answermemberSmith_TVPM4 Sep '06 - 21:16 
input pipe can help i think...
pls do some research
GeneralRe: Process waiting answermember12kaunas29 Mar '07 - 13:25 
I have the same problem trying to send the response to the process using wPipe. Can't make it working. Maybe somebody has this resolved.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 16 Apr 2005
Article Copyright 2005 by Smith_TVPM
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid