Executing external exe in a child window (C++, win32) - c++

I have written a simple win32 program say abc.exe.
I have added a button in it, clicking on which an external exe say xyz.exe should start.
But the original program i.e. abc.exe should be inaccessible while xyz.exe is running. (Same as in the case of message box where the parent window remains inactive unless message box is closed)
How can Ido it ?
It would be great if you could post an example code.

You can use WaitForSingleObject (IIRC) to wait for the new process to terminate. You can make your window not visible (e.g. via ShowWindow) before waiting. Check successful launch first.

When the button is pressed, create the 'xyz.exe' process using CreateProcess function and save the new process' handle (hProcess in the PROCESS_INFORMATION struct you passed in CreateProcess).
Then you can disable the 'abc.exe' window by calling EnableWindow with bEnable set to FALSE.
In the window procedure of 'abc.exe', where the WM_PAINT message is handled add a check to see if the 'xyz.exe' process is still running. You can do this by using GetExitCodeProcess function with the handle you saved earlier and checking if the return value is STILL_ACTIVE. If the 'xyz.exe' process is no longer active, you can then enable the 'abc.exe' window using EnableWindow again.

Related

MFC: Best place to prevent a window from re-appearing from a Restore operation

When my application is minimized, and the application programmatically closes a child window, the state of the child window between my framework and MFC goes out of sync because MFC will not send a WM_SHOWWINDOW message when the application is minimized. I noticed that Qt had the same problem: https://codereview.qt-project.org/#/c/93410/
Things that I have tried:
Override OnShowWindow() -- if the states are out of sync, then I alter the BOOL parameter before passing it to the CDialog::OnShowWindow. But doing so does nothing. It is as if the BOOL parameter given to the override is read-only.
Handle WM_SHOWWINDOW in PreTranslateMessage -- this does not work because WM_SHOWWINDOW does not appear here.
I know I can check SW_PARENTOPENING to know when to look for out-of-sync problems and handle it, but I just don't know where is the best place to do it.
My current solution is to override OnShowWindow, check for SW_PARENTOPENING, then post a SW_HIDE. It works, but it feels like a waste because I should be able to prevent it from restoring entirely rather than defer it.
Summary:
Basically, I am just programmatically closing a window, say from a timer call, or user's remote command, or whatever, while the main application is minimized. The dialog will be temporarily hidden when minimized (the MFC framework will automatically call ShowWindow(SW_HIDE) but with an internal flag to re-open when the app is restored). If my program sends ShowWindow(SW_HIDE) now, this call will not be registered, and the window will be re-opened by MFC when the app is maximized. To my user, he/she has closed the window remotely and does not expect the window to re-appear, so I need to re-call my ignored ShowWindow(SW_HIDE) somehow when restoring the main app.

What is the easiest way to handle window close event in WinAPI for the console application?

I'm writing a console multi-process application in c++ using WinAPI. So I have the Dispatcher(e.g. "Parent") and the Client(e.g. "Child") processes. Both processes are synchronized: they're using semaphors, events, mutexes and the pipe (all of them are standard WinAPI handles). Application stop when the user type the "exit" command. If the user do so, the dispatcher process notifies it's child, and then child releases its resources and makes another before-exit procedures to exit correctly. But there's a thing that bothers me: what will happen if the user press the window "close" button? If so, I should listen to close event and then perform my resource-releasing procedure. What is the easiest way to handle window close event?
Write a console handler routine that detects CTRL_CLOSE_EVENT (and CTRL_C_EVENT, if desired), and use SetConsoleCtrlHandler to add the handler routine to your process.
It isn't really different from the client process crashing or being terminated through Task Manager. You ought to be resilient to that as well. The ultimate signal you get for that in the parent process is that the client's process handle will be signaled.
Use WaitForMultipleObjects, along with those other handles, to detect this.

c++ windows - Disable crash dialog box in a child process

I have a program that launches a child process.
When the child process crashes I would like there not to be a debug message box. I would like to do this without writing anything in the child process.
I am running this on windows 7.
In the createProcess function, in the flags parameter I only put CREATE_NEW_CONSOLE.
During my attempts, I put SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX) in the child process and made it crash, there was no dialog box. Now I put the same function call in the parent program before I called create process, and made the child program crash, now the message box appeared.
What should I do differently?
have you set CREATE_DEFAULT_ERROR_MODE in process creation flags?

How to Cleanly Destroy WebBrowser Control

I am using ATL in VisualC++10 to host browser control.
My code is similar to this example: http://msdn.microsoft.com/en-us/library/9d0714y1(v=vs.80).aspx
Difference is I have main window and then child window hosts the browser control.
After 2 minutes i have to close the browser completely kill the browser activeX but this child window should be alive and do something else. But somehow this browser control still stays there, i can either see scrollbars or something..
I have also tried by creating child window to an existing child window, and at the time of closing browser I then destroy this child of a child - but still it does not work!
This is how I am closing:
CLOSE()
{
m_spIWebBrowser2->Navigate(bstrURL, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
m_spIWebBrowser2->Stop();
m_spIWebBrowser2->put_Visible(VARIANT_FALSE);
m_spIWebBrowser2->Quit();
DestroyWindow(m_wndChild.m_hWnd);
}
Thanks!
I had many problems with "access violation" when closing webbrowser control, these are the steps that worked for me:
Unadvise any previously advised events (DWebBrowserEvents2 in my case).
If you've attached click events unattach them like this: _variant_t v; v.vt = VT_DISPATCH; v.pdispVal = 0; IHTMLDocument2->put_onclick(v);
IWebBrowser2->Stop()
IWebBrowser2->ExecWB(OLECMDID_CLOSE, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0) - when closing browser window through window.external.CloseWindow() I had unhandled exceptions and OLECMDID_CLOSE fixed it.
IWebBrowser2->put_Visible(VARIANT_FALSE)
IWebBrowser2->Release()
IOleInPlaceObject->InPlaceDeactivate()
IOleInPlaceObject->Release()
IOleObject->DoVerb(OLEIVERB_HIDE, NULL, IOleClientSite, 0, windowHandle_, NULL)
IOleObject->Close(OLECLOSE_NOSAVE)
OleSetContainedObject(IOleObject, FALSE)
IOleObject->SetClientSite(NULL)
CoDisconnectObject(IOleObject, 0)
IOleObject->Release()
IWebBrowser2->Quit() should not be called for WebBrowser control (CLSID_WebBrowser), it is intended only for Internet Explorer object (CLSID_InternetExplorer).
Why must it be so hard?
My experience is that some calls might need message processing to function properly. Try to pump some messages between your calls to Navigate, Stop etc. When working with the web browser interfaces I PostMessage myself often to trigger the next step to make sure the previous step had time to complete.
The problem might be related to your child thread. You cannot access web browser interfaces between threads without some additional work. COM needs to be initialized as single-threaded apartment (STA). And you need to follow the rules of STAs:
Every object should live on only one thread (within a single-threaded apartment).
Initialize the COM library for each thread.
Marshal all pointers to objects when passing them between apartments.
Each single-threaded apartment must have a message loop to handle calls from other processes and apartments within the same process. Single-threaded apartments without objects (client only) also need a message loop to dispatch the broadcast messages that some applications use.
...
If I use DialogBox and drop a IEControl on it as a resource and DialogBox is derived from CAxDialogImpl<> - then while I call DestroyWindow() of dialogBox then it is automatically doing the cleanup() - which is what I required.
But originally I wanted to get rid of DialogBox itself and use IEControl directly on my Window, it seems not..

Create two windows in one application?

It might be a simple question, but I don't know where to start the search for the answer. How do I create two individual windows interface in one application using native winapi? Do I put two CreateWindow() functions using same HINSTANCE? What if I want a login screen windows and the content page such that login screen comes first, and after I press the button, the login screen is destroyed, and the content page appears. How do I do such trick?
I was thinking of using DestroyWindow and then CreateWindow inside the button click message. However, this would mean the main while loop (for translate/dispatch msg) in WinMain will exit its loop and cause the whole program to exit. Another way is to pre-create it in WinMain, but how would I notify the WinMain if the button was clicked and enter the second loop instead of exiting the program?
You're over-thinking it. To create two windows, call CreateWindow twice. It's just that simple.
Calling DestroyWindow does not cause your program to exit its message pump. Calling PostQuitMessage is what does that. So don't do that.
When the button is clicked, destroy the one window and create the other. There are no tricks. The message pump delivers messages to all windows (unless you're doing it wrong by explicitly requesting messages for one window, but you shouldn't do that).