CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    May 2004
    Posts
    28

    ShellExecuteEx process to HWND handle

    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?

  2. #2
    Join Date
    May 2005
    Posts
    4,954

    Re: ShellExecuteEx process to HWND handle

    you can try doing something like this:

    Code:
    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
    If a post helped you dont forget to "Rate This Post"

    My Article: Capturing Windows Regardless of Their Z-Order

    Cheers

  3. #3

    Re: ShellExecuteEx process to HWND handle

    Quote Originally Posted by golanshahar
    you can try doing something like this:

    Code:
    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.

    Code:
    if (pid == /*your process id*/)
    Best Api Monitor tool.
    Trace the target program automatically and monitor the parameters of all API and COM interfaces.

    Auto Debug for Windows 4.0
    Auto Debug for .Net
    http://www.autodebug.com/

  4. #4
    Join Date
    May 2004
    Posts
    28

    Re: ShellExecuteEx process to HWND handle

    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

  5. #5
    Join Date
    May 2005
    Posts
    4,954

    Re: ShellExecuteEx process to HWND handle

    Quote Originally Posted by pengch
    DWORD pid;
    DWORD dwTheardId = ::GetWindowThreadProcessId( h,&pid);


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

    no no no.


    Code:
    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
    Code:
    if (pid == /*your process id*/)
    however he doesnt have PID only handle to the process

    Cheers
    If a post helped you dont forget to "Rate This Post"

    My Article: Capturing Windows Regardless of Their Z-Order

    Cheers

  6. #6
    Join Date
    May 2005
    Posts
    4,954

    Re: ShellExecuteEx process to HWND handle

    Quote Originally Posted by keysman
    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(..)
    and for each Handle to the process you can use the ::GetGUIThreadInfo(..) and in the GUITHREADINFO you will have the hwnd you looking for.

    Cheers
    If a post helped you dont forget to "Rate This Post"

    My Article: Capturing Windows Regardless of Their Z-Order

    Cheers

  7. #7
    Join Date
    May 2004
    Posts
    28

    Re: ShellExecuteEx process to HWND handle

    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?

  8. #8
    Join Date
    Jul 2005
    Location
    Germany
    Posts
    1,194

    Re: ShellExecuteEx process to HWND handle

    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
    Please don't forget to rate users who helped you!

  9. #9
    Join Date
    May 2005
    Posts
    4,954

    Re: ShellExecuteEx process to HWND handle

    under 98 you can use the ::CreateToolhelp32Snapshot(..)
    anyway here is a code of mine that using it under 98/me, i added there an if that you should add.
    Code:
        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
    Last edited by golanshahar; August 12th, 2005 at 06:33 AM.
    If a post helped you dont forget to "Rate This Post"

    My Article: Capturing Windows Regardless of Their Z-Order

    Cheers

  10. #10
    Join Date
    May 2004
    Posts
    28

    Re: ShellExecuteEx process to HWND handle

    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.

  11. #11
    Join Date
    May 2005
    Posts
    4,954

    Re: ShellExecuteEx process to HWND handle

    dont lose hope dude, it will be solved !!
    i dont know why its not working...

    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(..) 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
    If a post helped you dont forget to "Rate This Post"

    My Article: Capturing Windows Regardless of Their Z-Order

    Cheers

  12. #12
    Join Date
    Jul 2005
    Location
    Germany
    Posts
    1,194

    Re: ShellExecuteEx process to HWND handle

    @keysman: I'm curious why my solution (FindWindow) does not work. Can you tell me, please?
    Please don't forget to rate users who helped you!

  13. #13
    Join Date
    May 2004
    Posts
    28

    Re: ShellExecuteEx process to HWND handle

    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured