Showing a progress bar while SFX archive is extracting - c++

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.

Related

Redirecting output from child processes

In my c++ windows app I start multiple child processes and I want them to inherit parent's stdout/stderr, so that if output of my app is redirected to some file then that file would also contain output of all child processes that my app creates.
Currently I do that using CreateProcess without output redirection. MSDN has a sample how to redirect output: Creating a Child Process with Redirected Input and Output, but I want to see what alternative do I have. Simplest is to use system and call it from a blocking thread that waits for child to exit. All output is then piped back to parent's stdout/stderr, however in parent process I do not have a chance to process stdout data that comes from child.
There are also other functions to start processes on windows: spawn, exec, which might be easier to port to posix systems.
What should I use if I want it to work on linux/osx? What options do I have if I want it to work on UWP aka WinRT? I might be totally ok with system called from a blocking thread, but perhaps I'd prefer to be able to have more control on process PID (to be able to terminate it) and process stdout/stderr, to prepend each line with child##: for example.
The boost libraries recently released version 1.64 which includes a new boost::process library.
In it, you're given a C++ way to be able to redirect output to a pipe or asio::streambuf, from which you can create a std::string or std::istream to read whatever your child process wrote.
You can read up on boost::process tutorials here, which shows some simple examples of reading child output. It does make heavy use of boost::asio, so I highly recommend you read up on that too.

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 can I perform network IO at the very end of a process' lifetime?

I'm developing a DLL in C++ which needs to write some data via a (previously established) TCP/IP connection using the write() call. To be precise, the DLL should send a little 'Process 12345 is terminating at 2007-09-27 15:30:42, value of i is 131' message over the wire when the process goes down.
Unfortunately, all the ways I know for detecting that the process is ending are apparently too late for any network calls to succeed. In particular, I tried the following approaches and the write() call returned -1 in every case:
Calling write() from the destructor of a global object.
Calling write() from a callback function registered using atexit().
Calling write() from DllMain (in case the reason argument is DLL_PROCESS_DETACH). I know that this is not a safe thing to do, but I'm getting a bit desperate. :-)
I'm aware that a DLL can't detect any process shutdown (it might have been unloaded long before the process terminates) but since the shutdown data which the DLL needs to send depends on other code in the DLL, that's acceptable. I'm basically looking for the latest moment at which I can safely perform network IO.
Does anybody know how to do this?
Consider monitoring the process from a separate watchdog process.
Determining If a Process Has Exited: http://msdn.microsoft.com/en-us/library/y111seb2(v=VS.71).aspx
Tutorial: Managing a Windows Process: http://msdn.microsoft.com/en-us/library/s9tkk4a3(v=VS.71).aspx
Consider to use Windows Job Objects.
You main program (monitoring program, which will use for example send()) can start child process suspended, place it into a Job and then resume. Then it will run in the job object. You can register notification via SetInformationJobObject with JobObjectAssociateCompletionPortInformation. Then you will be notified if in the job will be created some child process and if some process inside of job will be ended. So you will be able to send all what you need from the monitoring process. If you debug a program in Visual Studio it uses also job objects to have control under your process and all child processes which you start.
I successfully use the technique in C++ and in C#. So if you will have some problem with implementation I could post you a code example.
I suggest taking option 3. Just do your DLL loading/unloading properly and you're fine. Calling write() should work, I can't explain why it's not in your case. Is it possible that the call fails for a different reason that is unrelated?
Does it work if you call your DLL function manually from the host app?
Why? Just close the socket. If that's the only close in the program, which by your description it must be, that tells the other end that this end is exiting, and you can send the process ID information at the beginning instead of the end. You shouldn't do anything time-consuming or potentially blocking in an exit hook or static destructor.
Where is Winsock being shut down using WSACleanup? You need to make sure that your I/O completes before this happens.
You should be able to work out if this is happening by placing a breakpoint on the Win32 call in Winsock2.dll. Unload of DLLs is displayed in the output in the debug window.

is it is possible to run a background process if the window is closed?

I am creating an application in C++ gtk and if I press a button a threading process will start and I need to run the application if the window is closed also is it possible?
Under a Unix system (and since Windows 10), you create another process using the fork() function. To run a program you then use the execve() or similar.
However, that means you need to communicate with that other process using a pipe (see pipe() or pipe2()) or via the network.
Using a thread instead of a process allows you to run in the same memory & process and you can very easily shared everything between multiple threads.
As far as I know, the gtk loop just returns once the user selects the "Close Window" or similar exit function. It would be up for your main() function to make sure that it waits for all the threads to be done before exiting. For threads, this is usually done with a "join()". It will depend on the library you use to run your background process.
Note that in most cases people expect processes to exit whenever they ask the process to exit. Showing a window saying that your process is still running in the background (is busy) is a good idea for a process which runs a GUI. Especially, if you run your process from the console, it would not exit immediately after you closed the window, so letting the user know what's happening is important otherwise they are likely to hit Ctrl-C and kill the whole thing.
If you'd like the main to return but be able to keep the background threads running, it's a tad bit more complicated, but it uses both of the solutions I just mentioned:
create a pipe()
fork() (but no execve())
from within the forked app. (child) open Gtk window, background thread, etc.
when last Gtk window is closed, send message over pipe
parent process receives message and quits immediately
child process still attempts a "join()" to wait for the background thread
This way, the background process with threads created in (3) can continue to run (your function still needs to wait for all the threads to end with the "join()" call), however, the use has a sense of "the app. is done" since it returns to the next line on the prompt in your console even though a background process is still running.
The pipe() and wait on a message on the pipe() is not required if you don't mind having your application always running in the background.
Note: that usage of fork() is most often seen when creating processes that want to run in the background (i.e. services, often called servers under Unix). That's how they get their PPID set to 1.
On Windows, you need to create a Windows/Linux/Mac Service or run the process in background. On Linux you need to create a daemon service or run the process in the background. Services allow to automatically start the process on boot.

How to avoid thread preemption in C++, VisualStudio(Windows)

I developed a logger for testing our modules in c++, Win32 console, visual studio(Windows)
Logger is running in one thread.
While it displays output in console window, thread is getting preempted.
Some other module thread is running.
So output of other modules is getting mixed with output of Logger module in Console window.
Is there any way to avoid preemption of logger thread, so that entire logger output can be at one place in console output window ?
Writing to file instead of output window is one solution. But as the drive names may be different on different machines, its difficult to hardcode the logger output file path. Even then, we can still write the code for finding the drives available on any machine and write to first drive etc. But tester may not understand where to search for the logger output file.
Add the thread Id to the logger output, and then use a log viewer that can filter.
DebugView (under windows) allows you to add highlight filters to dynamic logging.
The standard solution is to use a mutex . After formatting, but before starting the output to the console, you lock the mutex. When all output is sent, you unlock the mutex again. If a second thread comes in, its attempt to lock the mutex will cause that thread to be preempted until the first thread is done.
CriticalSections in Windows behave mutex-like and are also usable. They use a slightly different terminology. You don't "lock" them, you "enter" and "leave" a critical section with EnterCriticalSection and LeaveCriticalSection.
Preventing Thread preemption is generally dangerous. You can try to temporarily increase the thread priority, but i dont advise it (Dangerous; will not work on multiprocessor, ...).
Other Ways:
rewrite all modules to only use your logger for output
if other modules only write to cout/stdout: logger should write to cerr/stderr. This will not prevent the intermingled output in the console. But when redirecting the program output to different files, it will.
I think the best solution is to simply separate the logger output from the rest of your program's output. You mentioned the possibility of writing the logging to a file. If your only hang-up with this solution is coding an appropriate path, then you can choose the output path dynamically:
TCHAR buffer[ MAX_PATH ];
SHGetSpecialFolderPath( NULL, buffer, CSIDL_LOCAL_APPDATA, TRUE );
This will give you the local app data folder for the current user. You can then just append your log file name.