Recent

Author Topic: Using SetWinEventHook to Track Window Creation  (Read 12173 times)

guest60499

  • Guest
Using SetWinEventHook to Track Window Creation
« on: June 24, 2017, 10:25:36 am »
Hopefully the code is self explanatory, I'm not sure what to add about it. What doesn't seem to work is that if I look for EVENT_OBJECT_CREATE events and filter them as below (which is similar to how one looks for all top level desktop windows in the result of an EnumWindows call) I will miss some events.

Notably creating an extra window in either Firefox or Chromium doesn't trigger an event like it should, or I am somehow not looking for the right thing. Any pointers? I'm not sure what to look for. I've started up Spy++ to investigate windows in the past but am not sure what to look for. I commented the styling check but when I create a new Firefox window I see nothing that is obviously related to Firefox and nothing with the proper title is printed.

The alternative to this is the SetWindowHookEx function which is far, far harder to use. However there is some indication it may be better working.

Code: Pascal  [Select][+][-]
  1. program PTile;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$calling stdcall}
  5.  
  6. uses
  7.   Classes, Windows;
  8.  
  9. type
  10.   HINSTANCE = HANDLE;
  11.   HWINEVENTHOOK = HANDLE;
  12.   WINEVENTPROC = procedure(
  13.     EventHook: HWINEVENTHOOK;
  14.     Event: DWORD;
  15.     HWnd: HWND;
  16.     IDObject, IDChild: LONG;
  17.     EventThread, EventTime: DWORD);
  18.   TInstallProcedure = procedure;
  19.   TUninstallProcedure = procedure;
  20.  
  21. const
  22.   WINEVENT_OUTOFCONTEXT = $0000;
  23.   EVENT_OBJECT_CREATE   = $8000;
  24.   EVENT_OBJECT_DESTROY  = $8001;
  25.   OBJID_WINDOW          = $0000;
  26.   INDEXID_CONTAINER     = $0000;
  27.  
  28. function SetWinEventHook(
  29.   EventMin, EventMax: UINT;
  30.   HMod: HMODULE;
  31.   EventProc: WINEVENTPROC;
  32.   IDProcess, IDThread: DWORD;
  33.   Flags: UINT): HWINEVENTHOOK; external 'User32.dll';
  34.  
  35. function UnhookWinEvent(
  36.   EventHook: HWINEVENTHOOK): LongBool; external 'User32.dll';
  37.  
  38. function {%H-}EnumWindowsCallback(
  39.   {%H-}HWnd: HWND;
  40.   {%H-}LParam: LPARAM): LongBool;
  41. begin
  42.   Result := True;
  43.   WriteLn('.');
  44. end;
  45.  
  46. procedure WinEventCallback(
  47.   {%H-}EventHook: HWINEVENTHOOK;
  48.   {%H-}Event: DWORD;
  49.   {%H-}HWnd: HWND;
  50.   {%H-}IDObject, {%H-}IDChild: LONG;
  51.   {%H-}EventThread, {%H-}EventTime: DWORD);
  52. var
  53.   Len: LongInt;
  54.   Title: array of WideChar;
  55.   LStyle: LONG;
  56. begin
  57.   if not ((Event = EVENT_OBJECT_CREATE) and
  58.           (IDObject = OBJID_WINDOW) and
  59.           (IDChild = INDEXID_CONTAINER)) then
  60.     exit;
  61.  
  62.   Len := GetWindowTextLengthW(HWnd) + 1;
  63.   if Len - 1 = 0 then
  64.     exit;
  65.  
  66.   SetLength(Title, Len);
  67.   GetWindowTextW(HWnd, @Title[0], Len);
  68.  
  69.   LStyle := GetWindowLong(HWnd, GWL_STYLE);
  70.   if LStyle = 0 then
  71.     exit;
  72.  
  73.   //if (LStyle and WS_BORDER) <> WS_BORDER then
  74.   //  exit;
  75.  
  76.   WriteLn(WideCharToString(@Title[0]));
  77. end;
  78.  
  79. var
  80.   Message: TMsg;
  81.   EventHook: HWINEVENTHOOK;
  82. begin
  83.   Message := Default(TMsg);
  84.   EventHook := SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, 0,
  85.     @WinEventCallback, 0, 0, WINEVENT_OUTOFCONTEXT);
  86.  
  87.   while GetMessage(Message, 0, 0, 0) do
  88.     DispatchMessage(Message);
  89.  
  90.   if EventHook <> 0 then
  91.     UnhookWinEvent(EventHook);
  92. end.

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: Using SetWinEventHook to Track Window Creation
« Reply #1 on: June 24, 2017, 01:59:49 pm »
Notably creating an extra window in either Firefox or Chromium doesn't trigger an event like it should, or I am somehow not looking for the right thing. Any pointers?
These browsers do not use window functions for tabs, but draw them themselves.

guest60499

  • Guest
Re: Using SetWinEventHook to Track Window Creation
« Reply #2 on: June 26, 2017, 07:14:13 am »
Notably creating an extra window in either Firefox or Chromium doesn't trigger an event like it should, or I am somehow not looking for the right thing. Any pointers?
These browsers do not use window functions for tabs, but draw them themselves.
Not a tab, an entire new window. I just don't get any event for it. As I mentioned in the main post I tried relaxing my filters to get more events, but I still don't see anything with the title of the new window. I have no idea what facet of the WinAPI Firefox is making use of to create windows in this way.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Using SetWinEventHook to Track Window Creation
« Reply #3 on: June 26, 2017, 07:22:30 am »
Not a tab, an entire new window. I just don't get any event for it. As I mentioned in the main post I tried relaxing my filters to get more events, but I still don't see anything with the title of the new window. I have no idea what facet of the WinAPI Firefox is making use of to create windows in this way.
Usual way of doing that would be for the main program to have threads that create their own 'tab'-windows. In which case your event-handler probably isn't able to 'catch' those events.

In case you are able to then you could check that by searching the window by title, then see to which (sub)thread the window with that title belongs.


guest60499

  • Guest
Re: Using SetWinEventHook to Track Window Creation
« Reply #4 on: June 26, 2017, 04:15:10 pm »
Not a tab, an entire new window. I just don't get any event for it. As I mentioned in the main post I tried relaxing my filters to get more events, but I still don't see anything with the title of the new window. I have no idea what facet of the WinAPI Firefox is making use of to create windows in this way.
Usual way of doing that would be for the main program to have threads that create their own 'tab'-windows. In which case your event-handler probably isn't able to 'catch' those events.

In case you are able to then you could check that by searching the window by title, then see to which (sub)thread the window with that title belongs.
That shouldn't be possible. The Firefox window that is created is a top-level desktop window, and looking for it in EnumWindows shows that it is visible and styled as a top-level window. However it seems like it is not created as such, and the Windows API that claims to be able to generate events on all window creation doesn't trigger an event for it.

What I'm trying to do is keep a list of windows active on the desktop. I can't search for title because that doesn't match my end goal. I can use EnumWindows to find all top-level desktop windows, but I don't want to have to regularly poll the desktop state.

Needless to say I am extremely confused. I've been looking at using SetWindowsHookEx but finding it extremely difficult to use - the code you want to run in a callback has to be in a DLL, and that DLL and the process which calls SetWindowsHookEx need to be the proper bitness to detect events in 32bit or 64bit programs. As it is I can't even get it to work for a single bitness.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: Using SetWinEventHook to Track Window Creation
« Reply #5 on: June 26, 2017, 11:33:51 pm »
Notably creating an extra window in either Firefox or Chromium doesn't trigger an event like it should, or I am somehow not looking for the right thing. Any pointers?

Using the code you provided (in Delphi, but it shouldn't matter), whenever FireFox creates a new tab, I DO get an EVENT_OBJECT_CREATE window event (just 1), but GetWindowTextLength() is always 0.  By comparison, when IE creates a new tab, I get a whole slew of EVENT_OBJECT_CREATE window events, and some of the windows have titles (usually class names) but most do not.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

guest60499

  • Guest
Re: Using SetWinEventHook to Track Window Creation
« Reply #6 on: June 27, 2017, 05:49:58 am »
Notably creating an extra window in either Firefox or Chromium doesn't trigger an event like it should, or I am somehow not looking for the right thing. Any pointers?

Using the code you provided (in Delphi, but it shouldn't matter), whenever FireFox creates a new tab, I DO get an EVENT_OBJECT_CREATE window event (just 1), but GetWindowTextLength() is always 0.  By comparison, when IE creates a new tab, I get a whole slew of EVENT_OBJECT_CREATE window events, and some of the windows have titles (usually class names) but most do not.
Some of those events aren't actually for the window but are for form elements on the window. I don't know of general way to match form elements to top level window creation.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Using SetWinEventHook to Track Window Creation
« Reply #7 on: June 27, 2017, 04:03:23 pm »
That shouldn't be possible.
Of course it can. There is no reason to prevent such a thing.

Quote
The Firefox window that is created is a top-level desktop window, and looking for it in EnumWindows shows that it is visible and styled as a top-level window.
Ok, that is good to know.

Quote
However it seems like it is not created as such, and the Windows API that claims to be able to generate events on all window creation doesn't trigger an event for it.
Correction. The "Active Accessibility User Interface Services" claims as such. And that is provided that the application is designed using that api.

Apparently the programs you tested and causes you headaches are not using that api.

Quote
What I'm trying to do is keep a list of windows active on the desktop. I can't search for title because that doesn't match my end goal.
The suggestion i made was not meant as an end goal, merely a suggestion to try understand the application (inner workings) a little better.

Quote
I can use EnumWindows to find all top-level desktop windows, but I don't want to have to regularly poll the desktop state.
Unless you are able to tap into the main program loop, i can't see how you would be able to do so otherwise.

Quote
Needless to say I am extremely confused.
I was confused as well. Now that i understand that this hook is meant for client/server applications, i understand a little better. Programs using this api produces these events, else they won't.

Quote
I've been looking at using SetWindowsHookEx but finding it extremely difficult to use - the code you want to run in a callback has to be in a DLL, and that DLL and the process which calls SetWindowsHookEx need to be the proper bitness to detect events in 32bit or 64bit programs. As it is I can't even get it to work for a single bitness.
afaik, only if you want to use that approach. The documentation on MSDN does provide information doing the same thing "out of context'. For the time being, i have no reason to doubt this hook works differently when working from inside a dll. The only difference i was able to find is that out of context also means "out of sync", but that is not the issue here.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: Using SetWinEventHook to Track Window Creation
« Reply #8 on: June 29, 2017, 01:20:11 am »
Correction. The "Active Accessibility User Interface Services" claims as such. And that is provided that the application is designed using that api.

Apparently the programs you tested and causes you headaches are not using that api.

*Standard* Win32 windows and controls already do use the API internally, though.  As such, most Windows apps are available to AAUI and UIAutomation by default without having to use any special coding to enable them.  It is usually only custom UI controls that need to use the API directly to expose their data.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

guest60499

  • Guest
Re: Using SetWinEventHook to Track Window Creation
« Reply #9 on: June 30, 2017, 04:37:47 pm »
That shouldn't be possible.
Of course it can. There is no reason to prevent such a thing.

Quote
However it seems like it is not created as such, and the Windows API that claims to be able to generate events on all window creation doesn't trigger an event for it.
Correction. The "Active Accessibility User Interface Services" claims as such. And that is provided that the application is designed using that api.

Apparently the programs you tested and causes you headaches are not using that api.
Can you cite the portion which says applications need to be designed to support the API? On some level I realize that a form which is entirely custom drawn won't have anything recognizable to the API as, say, buttons, but based on the available events I see no reason why the creation of a window - any window - shouldn't trigger a properly installed SetWinEventHook callback. See the comment by Mr. Lebeau.

Quote
I can use EnumWindows to find all top-level desktop windows, but I don't want to have to regularly poll the desktop state.
Unless you are able to tap into the main program loop, i can't see how you would be able to do so otherwise.
See below, this is how the SetWindowsHookEx function is implemented. I have less of an idea for SetWinEventHook.

Quote
Needless to say I am extremely confused.
I was confused as well. Now that i understand that this hook is meant for client/server applications, i understand a little better. Programs using this api produces these events, else they won't.
Except "using the API" is, as far as I can tell, using the normal Windows functions to manipulate form elements. The hook exists at the OS level so it's not unreasonable to expect it took trigger on everything. Nothing in the documentation I read seemed to indicate applications had to go out of their way to support it.

Quote
I've been looking at using SetWindowsHookEx but finding it extremely difficult to use - the code you want to run in a callback has to be in a DLL, and that DLL and the process which calls SetWindowsHookEx need to be the proper bitness to detect events in 32bit or 64bit programs. As it is I can't even get it to work for a single bitness.
afaik, only if you want to use that approach. The documentation on MSDN does provide information doing the same thing "out of context'. For the time being, i have no reason to doubt this hook works differently when working from inside a dll. The only difference i was able to find is that out of context also means "out of sync", but that is not the issue here.
For all but the mouse and window hooks it is required to have the callback be in a DLL and to pass a handle of a loaded copy of that DLL to SetWindowsHookEx. This is because Microsoft intends all of the hooks except those two to execute in the context of the hooked process. Based on some comments I found on the implementation of this it looks like there is code in the Windows event loop that calls the hooks provided by SetWindowsHookEx.

You can use things like WH_CBT or WH_SHELL without putting the code in a DLL. Your code will never run.

In any case I have actually tried to use SetWindowsHookEx with code in a DLL like it should be and am not having any luck. Any help would be appreciated with the question as posted; I may make a topic about SetWindowsHookEx in a few days.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Using SetWinEventHook to Track Window Creation
« Reply #10 on: July 06, 2017, 07:30:55 am »
Can you cite the portion which says applications need to be designed to support the API? On some level I realize that a form which is entirely custom drawn won't have anything recognizable to the API as, say, buttons, but based on the available events I see no reason why the creation of a window - any window - shouldn't trigger a properly installed SetWinEventHook callback. See the comment by Mr. Lebeau.
I'm more than happy to read the documentation for you but i think the discussion is moot, see below.

Quote
Except "using the API" is, as far as I can tell, using the normal Windows functions to manipulate form elements. The hook exists at the OS level so it's not unreasonable to expect it took trigger on everything. Nothing in the documentation I read seemed to indicate applications had to go out of their way to support it.
I believe you're to optimistic in that every application that runs on windows actually follows windows api. Most nowadays applications are cross platform and as such do not always follow usual conventions.

If you read the whole concept here then you'll be able to see for yourself that there are some hoops here and there. The number of events that are actually captured are pretty limited, for instance.

But, lets assume you're correct.

Quote
In any case I have actually tried to use SetWindowsHookEx with code in a DLL like it should be and am not having any luck. Any help would be appreciated with the question as posted; I may make a topic about SetWindowsHookEx in a few days.
I apologize for my delay. I've been trying to get some more information regarding this topic (running cross-platform applications to gather some results). I finally managed to get firefox installed and check that as well.

some snippet when testing firefox
Code: [Select]
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       Foreground  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =            Focus  ObjectID = Client
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00190220  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =          ReOrder  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     System  Action =       Foreground  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =            Focus  ObjectID = Client
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =          ReOrder  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       Foreground  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =            Focus  ObjectID = Client
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0014027E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00130150  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0016026C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00120154  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C01EE  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001E0192  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019019A  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00220198  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000B0174  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $004A024C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C019E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000C016C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002D0190  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002701D6  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000C0158  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $005301C2  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000C0156  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00230214  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01B8  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001B0160  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000E0124  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000F0152  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0012014A  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0017010E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =   2832  Window = $0018010E  Group =     Object  Action =          ReOrder  ObjectID = Window
  Process =   2816  Thread =   2832  Window = $0018010E  Group =     Object  Action =           Create  ObjectID = Window

So, that currently led me to believe that your applied filters are too tight.

Note that a window can be created but, specific properties can be adjusted later on in the game (and not every possible event is captured by the hook).

The above results are from opening some additional windows and tabs (which even makes me believe that tabs in firefox are using their own window. Other applications i've tested failed to trigger on such things because they use thei own custom solution for that).

guest60499

  • Guest
Re: Using SetWinEventHook to Track Window Creation
« Reply #11 on: July 06, 2017, 09:03:50 am »
Can you cite the portion which says applications need to be designed to support the API? On some level I realize that a form which is entirely custom drawn won't have anything recognizable to the API as, say, buttons, but based on the available events I see no reason why the creation of a window - any window - shouldn't trigger a properly installed SetWinEventHook callback. See the comment by Mr. Lebeau.
I'm more than happy to read the documentation for you but i think the discussion is moot, see below.
I read the documentation myself but didn't get what you did out if it, which is why I'm asking for a citation. The only reason I ask is because I want to avoid wasting time. As it is SetWinEventHook seems to be the most usable API and should do what I want. If it doesn't do what I want, I really need to know.

Quote
Except "using the API" is, as far as I can tell, using the normal Windows functions to manipulate form elements. The hook exists at the OS level so it's not unreasonable to expect it took trigger on everything. Nothing in the documentation I read seemed to indicate applications had to go out of their way to support it.
I believe you're to optimistic in that every application that runs on windows actually follows windows api. Most nowadays applications are cross platform and as such do not always follow usual conventions.

If you read the whole concept here then you'll be able to see for yourself that there are some hoops here and there. The number of events that are actually captured are pretty limited, for instance.
I'm vaguely aware of such APIs and think they accomplish something very different than what SetWinEventHook does.

That type of accessibility API looks like it aims to have developers encode useful information directly into the program so it can be used by accessibility services. On the other hand, SetWinEventHook simply allows you a la carte access to window events so you can make sense of them yourself. It doesn't necessarily try to guarantee you will be able to obtain the information you want from them.

As far as I can understand this is why I should be able to get the events that I want. Everything is hooked, and I'm receiving events for when processes call CreateWindow, SetWindowLong, etc. There seems to be no way to avoid having a program which creates a window generate callbacks for this method.

But, lets assume you're correct.

Quote
In any case I have actually tried to use SetWindowsHookEx with code in a DLL like it should be and am not having any luck. Any help would be appreciated with the question as posted; I may make a topic about SetWindowsHookEx in a few days.
I apologize for my delay. I've been trying to get some more information regarding this topic (running cross-platform applications to gather some results). I finally managed to get firefox installed and check that as well.

some snippet when testing firefox
Code: [Select]
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       Foreground  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =            Focus  ObjectID = Client
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00190220  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =          ReOrder  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     System  Action =       Foreground  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =            Focus  ObjectID = Client
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =          ReOrder  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       Foreground  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =            Focus  ObjectID = Client
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =       NameChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =           Create  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =   LocationChange  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =             Show  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     System  Action =     CaptureStart  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     System  Action =       CaptureEnd  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00040032  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =             Hide  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001A0220  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0014027E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00130150  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0016026C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0013026E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00120154  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002601E8  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00200260  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C01EE  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001E0192  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019019A  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00220198  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000B0174  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $004A024C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C019E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000C016C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002D0190  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $002701D6  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000C0158  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $005301C2  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000C0156  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $00230214  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01B8  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001B0160  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001C0208  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0019023A  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000E0124  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $000F0152  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0012014A  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $001F01D0  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0044021C  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =    168  Window = $0017010E  Group =     Object  Action =          Destroy  ObjectID = Window
  Process =   2816  Thread =   2832  Window = $0018010E  Group =     Object  Action =          ReOrder  ObjectID = Window
  Process =   2816  Thread =   2832  Window = $0018010E  Group =     Object  Action =           Create  ObjectID = Window

So, that currently led me to believe that your applied filters are too tight.

Note that a window can be created but, specific properties can be adjusted later on in the game (and not every possible event is captured by the hook).

The above results are from opening some additional windows and tabs (which even makes me believe that tabs in firefox are using their own window. Other applications i've tested failed to trigger on such things because they use thei own custom solution for that).
No need to apologize. I'm glad someone revisited the thread.

I can relax the filters and receive more events, but then I can't tell which ones are useful. Too many things seem to generate events. The output you provided is a useful reference because it shows just how many events are generated by a single window. I may need to find the time to go through some output with a very fine tooth comb, but I posted because I am perplexed that there is no simple 1:1 correspondence between window creation and EVENT_OBJECT_CREATE events.

Since you noticed, can you tell me which events are associated with opening a new window? As mentioned that is one of the things I could never find. Even with a very loose filter I only received one event and it had a nonsensical window title (of something not quite an internal component name). If you can answer this question I might be able to figure out why all window creation doesn't seem to trigger EVENT_OBJECT_CREATE. There's additional weirdness with Windows Store applications that I've yet to figure out as well. There might be a shortcut by using Windows API that is process oriented instead of window event oriented but that seemed like a worse solution based on the API I did find and was able to read about.

In the meantime I've hit a brick wall with SetWindowsHookEx too, so I might make a post about it. I still need to port everything to Pascal and might try making a daemon for both DLL bitnesses, but I can't even get the 64bit hooks to work by themselves using Mailslots for IPC.

Cheers,
    guest

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Using SetWinEventHook to Track Window Creation
« Reply #12 on: July 06, 2017, 01:43:00 pm »
I read the documentation myself but didn't get what you did out if it, which is why I'm asking for a citation.
1:
i have a tendency to read other things from documentation than usually 'accepted' by most. Thereby msn docs can be contradicting at times

2:
I would like to avoid the discussion who is right or wrong. In the end MS is right, and if not then they still are as somewhere it is probably written as they seem fit :-)

3.
i rather am in favor of solving the "problem" by code  :)

Quote
The only reason I ask is because I want to avoid wasting time.
fair enough, but that's also why i suggested to use less strict filters. That's usually easier done than pinpointing and interpreting ms docs.

Quote
If it doesn't do what I want, I really need to know.
Assuming that the application uses real Windows windows, then according to the documentation it should (with some minor difficulties with doing so across different application bitness, if i remember correctly).

Quote
It doesn't necessarily try to guarantee you will be able to obtain the information you want from them.
Actually i did read/interpreted as such. Even though receiving the event for another thread is out of sync to real time. e.g. events are 'trusted' to be received in the order that they appeared and  that's about it.

Quote
There seems to be no way to avoid having a program which creates a window generate callbacks for this method.
Assuming it's a windows Window, then yes i agree with that statement.

Tabbed "windows" are a bit more difficult to grasp because an application can re-use the same window, just as we could do with lazarus, f.i. a memo and a separate tab-bar (e.g. only refresh contents of the memo when tab is pressed and as such visually 'simulate' the 'switch' which could give user the impression there are several different windows/memo's).

Quote
I can relax the filters and receive more events, but then I can't tell which ones are useful. Too many things seem to generate events.
Yes, especially when you have many task running that generate a lot of events. That's why i capture all events and filter out later. edit: updated version filters upfront now.

In case you already know the process id then you could perhaps filter on that or use your test-even-filter-program to actually invoke the application that you wish to inspect.

Quote
The output you provided is a useful reference because it shows just how many events are generated by a single window. I may need to find the time to go through some output with a very fine tooth comb, but I posted because I am perplexed that there is no simple 1:1 correspondence between window creation and EVENT_OBJECT_CREATE events.
Looks can be deceiving. I have not investigated the window on a deeper level, simply because i was not looking for something in particular. I just wanted to know if windows are generated.

But... they might be just as well some (non-interesting) buttons that (also) appear on the (new) window. See also output below.

Quote
As mentioned that is one of the things I could never find. Even with a very loose filter I only received one event and it had a nonsensical window title (of something not quite an internal component name). If you can answer this question I might be able to figure out why all window creation doesn't seem to trigger
Well, in theory the create window object (referred to in my output as Group=object, Action=create, ObjectID=Window)

I'll try to add some more detailed information on the window create/destroy as well as the window show/hide events. See also below.

Do note however, that i test on winxp 32 bit. Mileage could perhaps vary for different windows versions and/or different versions of the inspected application.

Also note that FPC supplied unit headers do not contain the full list of all events. I had to add some of them myself from msdn docs (although those missing from the fpc headers should have no influence for what you would need/are interested in).

Complete startup/closedown sequence for firefox:
edit: attached as it exceeded message limit.

ps: please let know if such information would be enough to get your idea going.

guest60499

  • Guest
Re: Using SetWinEventHook to Track Window Creation
« Reply #13 on: July 12, 2017, 11:46:28 pm »
Thank you molly, that information was helpful.

On my to do list now is figuring out whether or not I can do the same test I do in EnumWindows as in the WinEventHook callback; that is, check for WS_VISIBLE in addition to WS_BORDER. For some reason it looked like no EVENT_OBJECT_CREATE events had the WS_VISIBLE style, so I had to remove the test for it; when it is removed things such as popup boxes will match the test listed in the original post if there is not a check for a title.

Unfortunately, it looks like some programs create untitled windows, so it seems I can't distinguish those windows from popup boxes.

I was going to consider running EnumWindows each time I received a "major" EVENT_OBJECT_CREATE event, but I came across a private API used by dwm-win32: RegisterShellHookWindowFunction. Since learning of this API I have found quite a number of questions involving it, far more than the other APIs. I am wondering if the search results show some kind of selection for the most accessible API (i.e. there are fewer results for the other ones because they don't work properly or are harder to use).

Hopefully I will get this ported to Pascal. Also on my list is producing a working example of code which uses SetWindowsHookEx. RegisterShellHookWindowFunction works the same way as it does under the hood, which implies to me it is the better API. It somehow abstracts away the requirement of providing both bitness of DLL and running a corresponding server of each bitness to collect IPC from your injected DLL instances.

To date I have not seen a working example of SetWindowsHookEx that uses the functionality I am interested in. I may have improperly copied the one example which was claimed to work that I did find, however, it used a hook type that was allowed to run outside of the context of the hooked process. I found documentation indicating that WH_SHELL can run outside of the context of the hooked process (i.e. you provide a function in your executable, not a DLL) however my attempt at getting the hook to work in that manner was unfruitful.

guest.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Using SetWinEventHook to Track Window Creation
« Reply #14 on: July 13, 2017, 01:18:31 am »
Quote
On my to do list now is figuring out whether or not I can do the same test I do in EnumWindows as in the WinEventHook callback; that is, check for WS_VISIBLE in addition to WS_BORDER. For some reason it looked like no EVENT_OBJECT_CREATE events had the WS_VISIBLE style,
That is also my observation (no WS_VISIBLE), and sounds fairly logic for such 'big' application.

Creating the window hidden allows for the application to prepare things quietly and out of sight from end-user.

I've attached another log, this time also adding the window flags in a more human readable form (output became a bit messy because of that).

That's also where i ended my endeavours. I have found no way of telling which window is (becoming) what exactly). The name change gives a few hints, but that is user configurable.

e.g. if user selects other starting page for a new tab, then you have no way of telling one window form the other (but i have not did a deep inspection for the windows).

I have not found a reverse method of telling if a window is a top-level window or otherwise. Enumwindows seems only possible in top-down manner, while afaik this requires a bottom-up approach.

Quote
so I had to remove the test for it; when it is removed things such as popup boxes will match the test listed in the original post if there is not a check for a title.
... which led me to believe that your (initial) filtering was too tight ;-)

Quote
Unfortunately, it looks like some programs create untitled windows, so it seems I can't distinguish those windows from popup boxes.
Exactly, not to mention .. then what ?

I'm a bit lost there, and msdn as well as SO where not able to provide any (at least for me) clear answers. You might also be interested in the (individual?) tabbed windows, in case they are indeed separate windows.

Quote
...but I came across a private API used by dwm-win32: RegisterShellHookWindowFunction. Since learning of this API I have found quite a number of questions involving it, far more than the other APIs.
Jedi seems to have a component for that, here although i have no hands on experience.

Quote
I am wondering if the search results show some kind of selection for the most accessible API (i.e. there are fewer results for the other ones because they don't work properly or are harder to use).
The magic of the interwebs :-)

For my program to be able to retrieve the modulename, i have literally found one single page mentioning how to do that the way i wanted to (all others i found where copies of that same page, with the same coding mistakes  :D), and i had to use undocumented API. How to find undocumented API ?

(i found it to be a bit overkill to use toolhelp snapshot)

People seem not interrested in these kind of things anymore, so information on such topics disappears into oblivion :-(

For illustration, there was a very good forum on 2d/3d graphics and game programming (named flipcode) where people wrote really good papers on graphics/gaming related topics, e.g., how to write your own 3d engine, or your own renderer from scratch, how shading works etc. but that site is now defunct (luckily some of the content is archived).

And unfortunately there are many more of such sites that have perished :-(

Quote
Also on my list is producing a working example of code which uses SetWindowsHookEx. RegisterShellHookWindowFunction works the same way as it does under the hood, which implies to me it is the better API.
Perhaps this example is able to shed a light on the topic ? No idea if that works for 64 bit though.

Quote
I found documentation WH_SHELL can run outside of the context of the hooked process (i.e. you provide a function in your executable, not a DLL) however my attempt at getting the hook to work in that manner was unfruitful.
I haven't had time to look further into that topic yet, as i'm rather busy. I'll try and see if i'm able to come up with something, but please don't hold your breath....
(and hopefully the links can keep you a bit busy ;D )

 

TinyPortal © 2005-2018