Reading output from createprocess
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3

Thread: Reading output from createprocess

  1. #1
    Join Date
    Sep 2005
    Posts
    62

    Reading output from createprocess

    Right now I am starting a process with createprocess and then reading the output with ReadFile

    Code:
    	SECURITY_ATTRIBUTES saAttr;
    	saAttr.bInheritHandle = TRUE;
    	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    	saAttr.lpSecurityDescriptor = NULL;
    	int exitcode;
    	HANDLE pipe_stdin_read, pipe_stdin_write;
    	HANDLE pipe_stdout_read, pipe_stdout_write;
    	HANDLE pipe_stderr_read, pipe_stderr_write;
    	int   result;  /* CreateProcess() return value and other use(s) */
    	STARTUPINFO startup;
    	PROCESS_INFORMATION process;
    	/* create the pipes for the standard I/O handles */
    	result = 1; /* error indicator */
    	pipe_stdin_read = pipe_stdin_write = INVALID_HANDLE_VALUE;
    	pipe_stdout_read = pipe_stdout_write = INVALID_HANDLE_VALUE;
    	pipe_stderr_read = pipe_stderr_write = INVALID_HANDLE_VALUE;
        /* standard in (stdin) */
    	if (CreatePipe(&pipe_stdin_read, &pipe_stdin_write, &saAttr, 0))
         /* standard output (stdout) */
    	  if (CreatePipe(&pipe_stdout_read, &pipe_stdout_write, &saAttr, 0))
         /* standard error (stderr) */
    		if (CreatePipe(&pipe_stderr_read, &pipe_stderr_write, &saAttr, 0))
                result = 0;
    	if (result) { /* not all pipes were created */
    		CloseHandle(pipe_stdin_read);
    		CloseHandle(pipe_stdin_write);
    		CloseHandle(pipe_stdout_read);
    		CloseHandle(pipe_stdout_write);
    		CloseHandle(pipe_stderr_read);
    		CloseHandle(pipe_stderr_write);
    		debug("ERROR getting process handles.");
    
    	}
    
    		/* initialize the STARTUPINFO structure */
    	memset(&startup, 0, sizeof(STARTUPINFO));
    	startup.cb         = sizeof(STARTUPINFO);
    	startup.dwFlags    = STARTF_USESTDHANDLES;
    	startup.hStdInput  = pipe_stdin_read;
    	startup.hStdOutput = pipe_stdout_write;
    	startup.hStdError  = pipe_stderr_write;
    
    
    	debug("Starting process");
    
    	try
    	{
    		result = CreateProcess(NULL,
    							 comm,         /* command line */
    							 &saAttr, &saAttr,   /* process, thread attributes */
    							 TRUE,         /* inherit (standard) handles */
    							 DETACHED_PROCESS | CREATE_SUSPENDED,
    							 NULL,
    							 ".",          
    							 &startup, &process);
    
    		if (result == 0) { /* process creation failed */
    			CloseHandle(pipe_stdin_read);
    			CloseHandle(pipe_stdin_write);
    			CloseHandle(pipe_stdout_read);
    			CloseHandle(pipe_stdout_write);
    			CloseHandle(pipe_stderr_read);
    			CloseHandle(pipe_stderr_write);
    			result = 0;
    		}
    
    
    		CloseHandle(pipe_stdin_read);
    		CloseHandle(pipe_stdout_write);
    		CloseHandle(pipe_stderr_write);
    
    		cout << "starting resume " <<endl;
    		ResumeThread(process.hThread);
    	  /* these handles aren't needed anymore by the parent process, and they
    		 have to be closed now or else the threads will continue trying to
    		 access the pipes */
    	}
    
    
    	// process creation failed.
    	catch(...)
    	{
    		debug("Exception caught starting process");
    
    		result = 0;
    		
    	}
    
    
    		DWORD dwRead,tdwRead,tdwAfail,tdwLeft;
    		char buff1[128];
    
    while ( ReadFile ( pipe_stdout_read, buff1, 128, &dwRead, NULL) && dwRead != 0 )
    {
    
    
    cout << buff1;
    
    
    }

    I have two problems,
    The first is when I output buff1, I am getting chunks of return output,
    This is the executing code:
    Code:
    while (1){
    			cout << "Blah "<< endl;
    			cout << endl;
    			cout << "Rotate this" <<endl;
    
    			cout << count++ <<endl;
    }

    But when the readfile outputs, it looks like this:
    Code:
    Blah
    q≡'▒
    Rotate this
    0
    Blah
    e this
    0
    
    Rotate this
    1
    Blah
    e this
    1
    
    Rotate this
    2
    Blah
    e this
    2
    
    Rotate this
    3
    Blah
    e this
    3
    
    Rotate this
    4
    Blah
    e this
    4
    
    Rotate this
    5
    Blah
    e this
    5
    
    Rotate this
    6
    Blah
    e this
    6
    
    Rotate this
    7
    Blah
    e this
    7
    
    Rotate this
    8
    Blah
    e this
    8
    
    Rotate this
    9
    Blah
    e this
    9
    I have tried clearing buff1, before the next read but it doesn't work either.

    Second problem is when I execute something that doesn't have a buffer right away, I need to be able to exit out of the while loop, and do something else. But I haven't found a good way to do this yet, I did give PeekNamedPipe a try, but that seemed to do the same thing.

    Any suggestions?


    Thanks
    Last edited by brokenchode; November 1st, 2005 at 05:02 PM.

  2. #2
    Join Date
    Apr 2003
    Posts
    1,755

    Smile Re: Reading output from createprocess

    You should output only the bytes you have read. Terminate the string you read so that bytes at the end of the data is not printed. You should also flush the ourput stream use (since cout is buffered) to see the output. Do this also with your test child app
    Code:
    buff1[dwRead] = '\0';
    cout << buff1;
    cout.flush();
    With the PeekNamedPipe, you should use it before each ReadFile. It's not working to you once the data has arrived because (maybe) you looped on reading without checking first if there is more data.
    Code:
    char buff1[128];
    DWORD dwRead,tdwRead,tdwAfail,tdwLeft, dwAvail, ctr = 0;
    while (PeekNamedPipe(pipe_stdout_read, buff1, 1, &dwRead, &dwAvail, &tdwLeft)) {
       if (dwRead) {
          if (ReadFile(pipe_stdout_read, buff1, sizeof(buff1) - 1, &dwRead, NULL) && dwRead != 0 ) {
             buff1[dwRead] = '\0';
             cout << buff1;
             cout.flush();
          }
       }
       else {
          sprintf(buff1, "No data loop count = %d. Do something here\n", ++ctr);
          cout << buff1;
          cout.flush();
          SleepEx(1000, FALSE);
       }
    }
    Hope it will help you

  3. #3
    Join Date
    Sep 2005
    Posts
    62

    Re: Reading output from createprocess

    Quote Originally Posted by rxbagain
    You should output only the bytes you have read. Terminate the string you read so that bytes at the end of the data is not printed. You should also flush the ourput stream use (since cout is buffered) to see the output. Do this also with your test child app
    Code:
    buff1[dwRead] = '\0';
    cout << buff1;
    cout.flush();
    With the PeekNamedPipe, you should use it before each ReadFile. It's not working to you once the data has arrived because (maybe) you looped on reading without checking first if there is more data.
    Code:
    char buff1[128];
    DWORD dwRead,tdwRead,tdwAfail,tdwLeft, dwAvail, ctr = 0;
    while (PeekNamedPipe(pipe_stdout_read, buff1, 1, &dwRead, &dwAvail, &tdwLeft)) {
       if (dwRead) {
          if (ReadFile(pipe_stdout_read, buff1, sizeof(buff1) - 1, &dwRead, NULL) && dwRead != 0 ) {
             buff1[dwRead] = '\0';
             cout << buff1;
             cout.flush();
          }
       }
       else {
          sprintf(buff1, "No data loop count = %d. Do something here\n", ++ctr);
          cout << buff1;
          cout.flush();
          SleepEx(1000, FALSE);
       }
    }
    Hope it will help you

    Thanks, terminating that line would of never came to me!, again many thanks!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center