How can I capture output of a console app in a loop - c++

My program runs a console program and captures the output using these functions:
CreatePipe, CreateProcess, WaitForSingleObject, ReadFile, and CloseHandle.
My program works great and displays the output in a window control.
If I am going to run a console app that will take a long time, instead of calling WaitForSingleObject, I'd like to call ReadFile within a loop and have the loop end when the console app does and the last message has been read.
All my attempts at this result in a forever loop and I have to kill the main program. Any advice would be appreciated. Thanks!

Related

Program stops when starting another executable using system()

I have a loop which checks to see if a certain process is active. If the process isn't active, the main program launches it using the system() call. Example:
#define MODERATING_INTERVAL 1000
...
while (true) {
if (!isProcessRunning())
system("helper.exe");
Sleep(MODERATING_INTERVAL);
}
My problem is that everything runs fine, but the main program is paused as long as the helper.exeprogram is running, so the loop will not iterate.
I couldn't find a solution myself, so I'm asking: is it possible to make the example loop continue iterating while the invoked program is running?
Thanks in advance.
This is the normal behaviour of system. If you want to start a new process that runs concurrently with your current program you need to use CreateProcess.

Is it possible to intercept calls to console from another process?

The situation is that I have program started through system() or CreateProcess().
Now, is it possible to do stuff as that program outputs data into console. I mean as the program outputs it. That is not wait for the end, gather data and then process it, but just in the moment that this external program calls console with data that it wants to print, and then get hold of that data, process it and output something else on the console.
The easiest way is usually to start the program with _popen(your_program, "r");. That will return a FILE * you can read from, and what it reads will be whatever the child writes to its standard output. When you read EOF on that file, it means the child process has terminated. This makes it relatively easy to read and process the output from the child in real time.
On Linux, create a named pipe:
system("mkfifo pipename")
Then open the pipe in the first program, and start the program with:
system("program > pipename")
I'm not sure how to do this on Windows.
Call AllocConsole before creating child process, or use AttachConsole(ChildPID) function (in parent process).
After that, you may use any ReadConsoleXXX or WriteConsoleXXX functions.

How to play sound at the same time as the program?

I want to play sound while the program is running in c++. I am using the code:
void fighterplanesound()
{PlaySound(TEXT("bombdrop.wav"), NULL, SND_FILENAME|SND_ASYNC);}
I thought the SND_ASYNC flag would fix this problem but it did not. What is happening is the program will pause or control will not move on until the sound is done playing. How can I play the sound while the program continues to run. To clarify, the program is a Windows console program that operates in an MS-DOS window.
How about playing the sound in a different thread?
Ok. What I figured out was that you can't include the PlaySound method in the function because even though the ASYNC flag was there, control had to fully execute the PlaySound method before returning, so don't put it in the function unless there is more code in the function(in which case the sound will play while that code is executing) or in other words, control will not return from the function until PlaySound is finished executing and because there is no other code in the function to execute, control waits until PlaySound method is finished and then moves on.
Actually i had the same problem on my iOS app. You know the time that how long does it take to play your .wav file. You can create a Timer that calls your fighterplanesound() method each period of ending time of your file. Not the best solution but it works for me.

Editline with non-blocking input

I use editline library in my program, for user commands input in shell. But becides shell, program have a gui interface, so I need to run editline's readline() function in separate thread, because it blocks until Enter pressed. Is there a way to use readline() function without blocking, so I could avoid separate thread usage?
Why not making the GUI thread run in a different thread and leave the console input in the main thread. You can push events to the GUI thread after reading from command line. It is much simpler in my opinion.
This works of course if your GUI allows you to run it in a different thread than the main one.
LATER EDIT: Couldn't you just create a text control/window and take the input from there? Once you press Enter it clears input - just like typing messages at a console? I believe it is much simpler to have everything in the GUI

Showing a progress bar while SFX archive is extracting

I'm writing a program with C++ and by native Win32 API. I'm creating a process from a SFX archive EXE in silent mode that no GUI is shown to user. But I want to show a progress bar in my application, while the SFX archive extracting.
How can I do that?
Thanks.
If the process you create produces some textual output to the standard output then you can probably parse that output somehow and show the progress. To know if it does, activate it in a command line windows and watch what you get from it.
win32's CreateProcess() allows you to redirect the standard output of the process to a pipe. This way you can receive the output as soon as it is produced.
If the process you're creating doesn't report its progress somehow then there's really not much you can do. You can try to come up with function between the size of the file and the average time it takes to extract it and then fake a progress bar. That will serve the purpose of setting the user's mind at ease but nothing more.
--Edit
The call to CreateProcess() returns as soon as the process is created. CreateProcess() fills up the struct PROCESS_INFORMATION with the handles of the process it creates. it contains the handle of the main thread of the process. If you want to wait for the process to finish you can WaitForSingleEvent() on that thread handle which gets signaled when the thread terminates. Don't forget to CloseHandle() those handles when you're done with them.