Click here to Skip to main content
15,884,425 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
Using the code below to run an external exe file, when this app terminates, the parent window loses its focus. I want to disable the parent window to avoid any paint problems and re-activate when the WaitForSingleObject is terminated.

Is there any solution for that ? What am i doing wrong ?

C++
void CMainFrame::OnBtnUpdateApp() {

    SHELLEXECUTEINFO    lpExecInfo;
    DWORD               dwExitCode;
    HINSTANCE           hProcess = 0;
    BOOL                bResult;



    ZeroMemory(&lpExecInfo,sizeof(lpExecInfo));
    lpExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    lpExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    lpExecInfo.hwnd = GetSafeHwnd();
    lpExecInfo.lpVerb = _T("open");
    lpExecInfo.lpFile = _T("Update.exe");
    lpExecInfo.lpParameters = _T("");
    lpExecInfo.lpDirectory = _T("");
    lpExecInfo.nShow = SW_SHOWNORMAL;
    lpExecInfo.hInstApp = NULL;
    lpExecInfo.hProcess = hProcess;

    bResult = ShellExecuteEx(&lpExecInfo);

    if(bResult) { 

         EnableWindow(FALSE);
         WaitForSingleObject( lpExecInfo.hProcess, INFINITE );

         if (!GetExitCodeProcess(lpExecInfo.hProcess, &dwExitCode)) {
                //failed to terminate normally   
         }

         CloseHandle(lpExecInfo.hProcess);
         EnableWindow(TRUE);

    } else {

        //failed to execute the exe file
    }


}


What I have tried:

I tried, BringWindowToTop(), SetActiveWindow(), SetFocus()
Posted
Updated 12-Jan-18 2:54am
Comments
[no name] 16-Feb-16 17:35pm    
Try calling Activate after the wait or ... before the wait - save the HWND from GetFocus and (after the wait) call SetFocus on the saved HWND.
sdancer75 17-Feb-16 12:29pm    
Using the code : HWND hfocus = ::GetFocus();EnableWindow(FALSE);WaitForSingleObject( lpExecInfo.hProcess, INFINITE );::SetFocus(hfocus);EnableWindow(TRUE); did not seem to work. Any other ideas ?
Frankie-C 20-Feb-16 13:50pm    
You cannot set focus on a disabled window. Enable window then set focus.
sdancer75 22-Feb-16 5:22am    
Yes that's true, my mistake.... but I have already did that and it didn't work.

Anyway I have some thoughts about the parent window that calls the shellexectute.
If my app is the parent window and the shellexecute app is the child window, does the switching using the keys Alt+Tab will show both parent and child apps ? This is what happens right now but I think that it would show only the parent window correct ? Does this have any relation with the focus control?
Frankie-C 22-Feb-16 5:38am    
there are many tricky things related to the window state, the calling thread etc.
Have you tried using SetForegroundWindow()?

You will get more control over the new process you are creating if you use CreateProcess() instead of ShellExecuteEx() and running Update.exe in the background.

C++
SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	BOOL ret = FALSE;
	DWORD flags = CREATE_NO_WINDOW;

	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags |= STARTF_USESTDHANDLES;
	si.hStdInput = NULL;
	si.hStdError = h;
	si.hStdOutput = h;

	CString cmd = _T("cmd /c ") + _T("Update.exe");
	BOOL inherits = FALSE;

	ret = CreateProcess(NULL,
		cmd.GetBuffer(),
		NULL,
		NULL,
		inherits,
		flags,
		NULL,
		NULL,
		&si,
		&pi);

	DWORD dwExitCode = 0;
	if (ret)
	{
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		return TRUE;
	}
 
Share this answer
 
v2
Comments
sdancer75 12-Jan-18 8:42am    
Hi, thank you for your solution. This questions is about 2 years old now, but i have already tested createprocess and shellexecute. Both of them methods loose their focus in some cases.

I found a justified solution for different cases using either shellexecute or createprocess. They seem to work fine with some restrictions.

I copied your code to verify if it works better than the code already implemented.
Michael Haephrati 12-Jan-18 8:44am    
Please post an answer to your own question. It would be useful to others facing a similar problem.
void CMainFrame::OnBtnUpdateApp() {


	PROCESS_INFORMATION processInfo;
	DWORD				dwExitCode;
	HANDLE				hProcess = 0;
	BOOL				bResult;
	CString				strCmd;
	CUtils				util;
	CString				strPathAndApp;


	strCmd = _T("");



	MONITORINFO mi = { sizeof(mi) };
	::GetWindowPlacement(GetSafeHwnd(), &m_g_wpPrevFrameSize) && ::GetMonitorInfo(MonitorFromWindow(GetSafeHwnd(),MONITOR_DEFAULTTOPRIMARY), &mi);

	strPathAndApp = _T("\"") + util.GetApplicationPath() + _T("\\")+_T(UPDATE_EXE_FILE) + _T("\"") + strCmd;	
	//******************************************************************************************
	//Pass the File + Parameters to cmdLine because otherwise it wont run under Winsows XP
	//******************************************************************************************
	bResult = StartupApplicationWithProcess (NULL, strPathAndApp.GetBuffer(),  &processInfo); //CreateProcess goes here
	strPathAndApp.ReleaseBuffer();


	if(bResult) { //(UINT)result > HINSTANCE_ERROR)
	
		
		AMLOGINFO(_T("LiveUpdate dialog box opened successfully."));

		DWORD dwRet;

		do {
			dwRet = ::MsgWaitForMultipleObjects(1, &processInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT);
			if (dwRet != WAIT_OBJECT_0) {

				PeekMessageLoop();
			}
		} while ((dwRet != WAIT_OBJECT_0) && (dwRet != WAIT_FAILED));

		   

		
		if (!GetExitCodeProcess(processInfo.hProcess, &dwExitCode)) {
			   	AMLOGINFO(_T("LiveUpdate is not terminated normally.")); 
		}

		CloseHandle( processInfo.hProcess );
        CloseHandle( processInfo.hThread );
		



		AMLOGINFO(_T("LiveUpdate is terminated without any errors.")); 
		
		 

	} else {

		CString ErrorDescr = FormatErrorMessage(GetLastError()); 

		AfxMessageBox("Error !");
		
		
	}

    SetForegroundWindow();
    SetActiveWindow();    
	BringWindowToTop();	
	UpdateWindow();
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900