1

I've been searching for an answer regarding this issue for a few days now, I hope you guys will be able to assist me. (I've searched and found some solutions, but each has its own issue...).

Here is the thing: I'm writing an automation at work, which is responsible for launching an external ".exe" file of a code written by my colleagues. As those programs they write go to customers, I'm not allowed to make any modification to their code. Those programs, once launched, are waiting for specific key strokes, and prints a message when a legal key stroke has been received.

My goal is this: To write a program which will execute the external program, send it key strokes, and receive the output from their stdout. So far, I have been able to run the program from my program (using ShellExecute), and simulate some sort of keyboard listener (using SendMessage) to the other program. I can see that it works - I can see the output in the tested program's console.

I'm trying to fetch the messages printed on the tested program's shell in real-time (and just get a bulk of data when the program terminates) so that I could analyse it when it occurs.

Those I've tried:

  • Writing an external batch file with inline output redirection to a text file.
  • Using freopen.
  • Redirecting the output while exectuing "ShellExecute".
Mat
  • 202,337
  • 40
  • 393
  • 406
Idanis
  • 1,918
  • 6
  • 38
  • 69
  • You can not redirect output while using ShellExecute. Similar mechanism in .net: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx – Mohammad Jun 24 '12 at 10:49
  • possible duplicate of [Read another process' stdout in C++](http://stackoverflow.com/questions/4093252/read-another-process-stdout-in-c) – Bo Persson Jun 24 '12 at 10:50

1 Answers1

0

You use handles for stdin, stdout, and stderr. Create process with CreateProcess function to get that handles. Sample code - incomplete for your case, but good example of how to do it:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

    /*for test.exe
#include <iostream>
#include <string> */

void _tmain( int argc, TCHAR *argv[] )
{
    /*for test.exe
    std::cout << "test output" << std::endl;
    for (;;)
    {
        std::string line;
        std::getline(std::cin, line);
        std::cout << "line: " << line << std::endl;
    }
    return;*/
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        "test.exe",        // 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;
    }

   /*     HANDLE  hStdInput;
    HANDLE  hStdOutput;
    HANDLE  hStdError;*/
    HANDLE me_hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE me_hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    HANDLE proc_hStdInput = si.hStdInput;
    HANDLE proc_hStdOutput = si.hStdOutput;

                char buff[64];
                DWORD chars;
    while (!ReadConsole(me_hStdInput, buff, sizeof(buff), &chars, NULL))
    {
                    for (DWORD written = 0, writtenThisTime; written < chars; written += writtenThisTime)                   
                        if (!WriteConsole(proc_hStdOutput, buff + written, chars - written, &writtenThisTime, NULL))
                        {
                            //handle error - TODO
                        }
                }
                //possibly handle error for ReadConsole - TODO  


    // Wait until child process exits.
    //WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}
peenut
  • 3,366
  • 23
  • 24
  • STARTUPINFO is an input parameter used to provide options for creating processes, not an output parameter that will receive any information about the created process. STARTUPINFO.hStdInput, etc. will all be NULL after calling CreateProcess in the example above-- it won't work. – Cain T. S. Random Sep 06 '12 at 20:15
  • Be careful passing a literal or constant to CreateProces(). It's a common gotta, and results in undefined behavior since CreateProcess() will temporarily write to this location. See answer here: http://stackoverflow.com/questions/9427008/what-should-the-second-parameter-of-createprocess-be – namezero Jan 26 '14 at 00:59