Click to See Complete Forum and Search --> : ShellExecuteEx process to HWND handle


keysman
August 11th, 2005, 11:31 AM
Hi everyone. This is the problem. I execute an applicaton with ShellExecuteEx. In the structure SHELLEXECUTEINFO I receive HINSTANCE of the app and HANDLE of the process.

I need HWND of the created window.

I can't use statement "EnumWindow" 'cause the caption text of the created window change every time.
Using spy++ I can't get (I think) useful information: #32770 (Dialog) is the same for other dialogs too, so I can't use it.

Can someone help me?

golanshahar
August 11th, 2005, 11:42 AM
you can try doing something like this:


HWND h = ::GetTopWindow(0 );

while ( h )
{
DWORD pid;
DWORD dwTheardId = ::GetWindowThreadProcessId( h,&pid);


HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);

if ( hProc == /*your process handle*/ )
{
// here h is the handle to the window
break;
}
h = ::GetNextWindow( h , GW_HWNDNEXT);
}


hope it will help

Cheers

pengch
August 12th, 2005, 12:00 AM
you can try doing something like this:


HWND h = ::GetTopWindow(0 );

while ( h )
{
DWORD pid;
DWORD dwTheardId = ::GetWindowThreadProcessId( h,&pid);


HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);

if ( hProc == /*your process handle*/ )
{
// here h is the handle to the window
break;
}
h = ::GetNextWindow( h , GW_HWNDNEXT);
}


hope it will help

Cheers

DWORD pid;
DWORD dwTheardId = ::GetWindowThreadProcessId( h,&pid);


HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);
????

no no no.

if (pid == /*your process id*/)

keysman
August 12th, 2005, 01:58 AM
Thanks guys, but this is the situation:

golanshahar: your solution does not seem to go

pengch: I can't use your solution 'cause I have not the pid (DWORD) of created process but only an handle (HANDLE ).

If you know another way please tell me. I have to run an external function with RUNDLL32.EXE. Do you know another way to catch the HWND of the created window?

Thanks

golanshahar
August 12th, 2005, 01:59 AM
DWORD pid;
DWORD dwTheardId = ::GetWindowThreadProcessId( h,&pid);


HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);
????

no no no.



if (pid == /*your process id*/)



you probably didnt understand what i am trying to do here :)
first of all if you have seen the question you would have seen that he needs to get the HWND out of HANDLE to the process.
so my code above runs on all top windows and on each one getting out the PID and via ::OpenProcess ( ) getting the handle to the process if the Current HANDLE == to the HANDLE he got from Shellexecute hence the HWND was found.

what you suggested is also work and vaild code

if (pid == /*your process id*/)

however he doesnt have PID only handle to the process ;)

Cheers

golanshahar
August 12th, 2005, 02:11 AM
Thanks guys, but this is the situation:

golanshahar: your solution does not seem to go

pengch: I can't use your solution 'cause I have not the pid (DWORD) of created process but only an handle (HANDLE ).

If you know another way please tell me. I have to run an external function with RUNDLL32.EXE. Do you know another way to catch the HWND of the created window?

Thanks


can you tell me please what exactly not working? can you post your project here so i can take a look?

there is another way btw to ::EnumProcesses(..) (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/enumerating_all_processes.asp)
and for each Handle to the process you can use the ::GetGUIThreadInfo(..) (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/getguithreadinfo.asp) and in the GUITHREADINFO you will have the hwnd you looking for.

Cheers

keysman
August 12th, 2005, 05:50 AM
Ok. I can't use EnumProcess 'cause I still working with win9x.
I run Dialup dialog using "rundll32.exe rnaDial,.....".
I have to get HWND of the Dialup dialog.

This is the problem. Can you help me?

philkr
August 12th, 2005, 05:58 AM
I would suggest the following.

1) Open the dialup dialog
2) Use this neat Spy++ tool which comes with VC++ to find out class name and window caption
3) Put a FindWindow() call in your program with class name and window caption as parameter

golanshahar
August 12th, 2005, 06:20 AM
under 98 you can use the ::CreateToolhelp32Snapshot(..) (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/createtoolhelp32snapshot.asp)
anyway here is a code of mine that using it under 98/me, i added there an if that you should add.

HINSTANCE h = ::GetModuleHandle ( "Kernel32.dll" );
if ( h == NULL )
h = ::LoadLibrary("Kernel32.dll");
if (h == NULL )
return;

typedef HANDLE (WINAPI *tCreateToolhelp32Snapshot) ( DWORD,DWORD );
typedef BOOL (WINAPI *tProcess32First) ( HANDLE,LPPROCESSENTRY32 );
typedef BOOL (WINAPI *tProcess32Next) ( HANDLE,LPPROCESSENTRY32 );

tCreateToolhelp32Snapshot pCreateToolhelp32Snapshot = (tCreateToolhelp32Snapshot)::GetProcAddress(h,"CreateToolhelp32Snapshot");
tProcess32First pProcess32First = (tProcess32First)::GetProcAddress(h,"Process32First");
tProcess32Next pProcess32Next = (tProcess32Next)::GetProcAddress(h,"Process32Next");

if ( pProcess32Next && pProcess32First && pCreateToolhelp32Snapshot )
{
HANDLE hSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,dwID);
PROCESSENTRY32 PE;
PE.dwSize = sizeof(PROCESSENTRY32);
pProcess32First(hSnap,&PE);
do
{
HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, 0, PE.th32ProcessID);

if (hProc == /*your process handle*/)
{
GUITHREADINFO Gti;
::ZeroMemory ( &Gti,sizeof(GUITHREADINFO));
Gti.cbSize = sizeof( GUITHREADINFO );
::GetGUIThreadInfo(PE.th32ProcessID,&Gti);
// in Gti you will find the handle Gti.hwndActive
break;
}
}
while(pProcess32Next(hSnap,&PE));
::CloseHandle (hSnap);
}


NOTE: i didnt compile it but it should work! ;)
hope it helps

/EDIT in the sample code above i used dynamic loading cause on win2000 i used EnumProcess(..) so instead using #ifdef i checked via GetVersionEx(..) what type of OS i am running and accroding to that i knew what functions to use, you on the other hand if you use only win98 you can avoid the dynamic loading if you want and call directly the functions.

Cheers

keysman
August 12th, 2005, 07:40 AM
Sorry golanshahar but this does not seem to go too or I mistake something.

With ShelleExecuteEx(&ShExecInfo) i run "rundll32.exe rnaui.dll,RnaDial myconn". And all is right.

ShExecInfo receive (ShExecInfo.hProcess) Handle to the newly started application. This is the one I pass to your code(I use it like my process handle). However this is never find. While debugging I see all process handle and there is noone as same as ShExecInfo.hProcess.

What's up?????

I'm losing every hopes.
:cry:

golanshahar
August 12th, 2005, 09:41 AM
dont lose hope dude, it will be solved !!
i dont know why its not working...:confused:

BUT we can try other way around like philkr offered before. when the Dialog of dial-up is open make sure its Caption is not changing and if so simply use the ::FindWindow(..) (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/findwindow.asp) api and it will return you the Handle to the window.
now this must work...if the caption is changing then we will find away maybe via class name to find it.
let me know the outcome...

Cheers

philkr
August 13th, 2005, 02:54 AM
@keysman: I'm curious why my solution (FindWindow) does not work. Can you tell me, please?

keysman
August 14th, 2005, 11:49 AM
Ok Philkr, sorry If I don't answer fast but I've hard work in this days.
In WinXP/2K there are no troubles, because with EnumWidows I can get the caption of each window, where inside there is the dialup connection name, so I can use StrStr to check if the dialog is that I was running.

In Win9x/Me the question is a bit different. In this kind of OS the dialup connection dialog don't merge the connection name (unlike winXP/2K).

Using Spy++, if you open two or more dialup dialog, you get the same Class value: so FindWindow could get the wrong hwnd. This is bad for me 'cause I have to get exactly the dialup connection dialog I was started.

My problem is get exactly the HWND of dialup dialog that I was started, cause I have to send a message (SendMessage) to this dialog.