// JP opened flex table

Click to See Complete Forum and Search --> : getting WindowHandle from CreateProcess


flynny1st
April 19th, 2007, 11:27 AM
Hi,

I'm having a small problem using Create process. I'm trying to run an external program using createProcess(). This is working fine and the program (i'm testing it using calc) is loading ok. Now i want to get hold of the window handle (HWND__*) of the new process in this case calc.

I've tried the following code however it crashes out. Can anyone tell me whats going wrong with the code or another method to retrieve this handle?


STARTUPINFO siStartInfo;
PROCESS_INFORMATION piProcessInfo;

GetStartupInfo(&siStartInfo);
CreateProcess(NULL, "Calc", NULL,NULL,FALSE,0,NULL,NULL,&siStartInfo,&piProcessInfo);

AppHook = FindProgWindow("Calculator");


FindProgWindow("prog name"); is a methos i have in a DLL. this is simply


DllExport HWND__* WINAPI FindProgWindow(CString progName)
{
return FindWindow(NULL, progName);
}


The program breaks out with the message

User breakpoint called from code at 0x7c901230

I have also tried replacing FindProgWindow("Calculator"); with FindWindow(NULL, "Calculator"); and this just returns 0.

Any Ideas?
thanks Matt.

MrViggy
April 19th, 2007, 12:11 PM
Well:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/findwindow.asp

What does "GetLastError" return when FindWindow returns 0?

Viggy

flynny1st
April 23rd, 2007, 10:08 AM
Hi,

Thanks for the reply i've worked the problem out with using findWindow(). I simply needed to use the sleep(70) to wait until the program has loaded before i try and hook into.

It now adds my button to the calculator but is still causing problems as clicking it does nothing and it is not refreshing the button if another window is moved over it. I know the hooks are being created as neither are returning zero.

(These are events i have had working before as at first i had it as an Win32 application, however as i now don't want the form to appear i have rewritten it as a console application.)

Can anyone help?

Matt.

flynny1st
April 23rd, 2007, 10:34 AM
Delving deeper the problem seems to be with my getMessage() command as once i have loaded the program added my button and hooked into it i then want to poll the program until WM_QUIT is retrieved, once this happens i can unhook and exit.

heres the code can anyone see what im doing wrong?


while( GetMessage(NULL,ThisHook,0,0) )
{
//do nothing until =0 and wm_quit is called
}

return 0;

chals1
April 23rd, 2007, 02:54 PM
I think there was a command named GetHandleFromPid in FBSL, a basic language

ovidiucucu
April 23rd, 2007, 07:53 PM
I simply needed to use the sleep(70) to wait until the program has loaded before i try and hook into.
Are you sure that sleeping 70ms is always enough (could be too much as well)?
Safer, once you have called CreateProcess and yo've got the handle to that process, you can use WaitForInputIdle (http://msdn2.microsoft.com/en-us/library/ms687022.aspx) to wait until that process has finished its initialization.
FindWindow(NULL, progName);
Generally, the worst idea is to find a window given its text.
Better, in case of calc application you can use its main window class name ("SciCalc") or, better than better, once you have called CreateProcess and you've got the ID of main thread, you can use EnumThreadWindows (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/enumthreadwindows.asp)

Here is a complete example:

HWND hWndCalc = NULL;

BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam)
{
hWndCalc = hWnd; // got the calc main window...
// ... start hooking or whatever, then...
return FALSE; // ...stop enum
}
// ...
STARTUPINFO siStartInfo = {0};
PROCESS_INFORMATION piProcessInfo = {0};

CreateProcessA(NULL, "Calc",
NULL, NULL, FALSE, 0, NULL, NULL,
&siStartInfo,&piProcessInfo);

if(0 == WaitForInputIdle(piProcessInfo.hProcess, 5000))
{
EnumThreadWindows(piProcessInfo.dwThreadId,
EnumThreadWndProc, NULL);
}
else
{
MessageBoxA(NULL, "Could not start calculator",
"Error", MB_OK|MB_ICONERROR);
}
// ...

TheCPUWizard
April 23rd, 2007, 08:45 PM
I wholeheartedly support the use of EnumThreadWindows. It has proven (to me) that it is the most reliable, and typically the most performant. I have had some issues during stress testing on Win-2000 Advanced Server, if I have over about 700 main windows open (and am nearly at resource exhaustion). But I have never found this to be a real world scenario.

ovidiucucu
April 23rd, 2007, 09:06 PM
But I have never found this to be a real world scenario.
I put that just for real life scenarios in that real world programmers tend to search for window caption texts. ;)

flynny1st
April 24th, 2007, 06:06 AM
ok, ovidiucucu i've followed what you said and i'm adding the callback function to my program.

However is it possible to add a callback function to a console application? or will i have to add it to my dll?

the code i have at the moment will is



int main(int argc, char* argv[])
{
...
STARTUPINFO siStartInfo = {0};
PROCESS_INFORMATION piProcessInfo = {0};

GetStartupInfo(&siStartInfo);
CreateProcess(NULL, "Calc", NULL,NULL,FALSE,0,NULL,NULL,&siStartInfo,&piProcessInfo);

if(WaitForInputIdle(piProcessInfo.hProcess, 5000) == 0)
{
EnumThreadWindows(piProcessInfo.dwThreadId, EnumThreadWndProc, NULL);
}
else
{
MessageBoxA(NULL, "Could not start calculator","Error", MB_OK|MB_ICONERROR);
}
}

BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam)
{
AppHook = hWnd; // got the calc main window
AppHInstance = FindWindowHInstance(AppHook);
AppProcessID = FindWindowProcess(AppHook);

ButtonHook = CreateButton(220, 63, 45, 30, AppHook, AppHInstance, NULL);
ButtonHInstance = FindWindowHInstance(ButtonHook);
ButtonProcessID = FindWindowProcess(ButtonHook);

if(AppProcessID != 0)
{
MouseHook = InstallMouseLauncher(NULL, ButtonProcessID, ButtonHook);
EventsHook = InstallEventsLauncher(ButtonHInstance, ButtonProcessID, ButtonHook, ThisHook);

sprintf(hook, "MouseHook %d, Events %d", MouseHook, EventsHook);
MessageBox(NULL,hook,NULL,0);
}


return FALSE; // ...stop enum
}



however it compiling with this gives the following errors.

error C2065: 'EnumThreadWndProc' : undeclared identifier
error C2373: 'EnumThreadWndProc' : redefinition; different type modifiers

any ideas? thanks for the help.

Matt

flynny1st
April 25th, 2007, 04:14 AM
Hi,

Ok i've pulled the callback method into my dll and its now working fine.

thanks for the help.

Matt.

//JP added flex table