Win32 - Can one Enumerate the windows belonging to the calling thread? - ruby

From MSDN on GetActiveWindow
"Retrieves the window handle to the active window attached to the calling thread's message queue."
I'm writing SketchUp plugins using its Ruby API. Currently trying to make some tweaks to some windows via the Win32. From the Ruby API I have very limited info about SU's window and thread. GetActiveWindow works fine as long as the SketchUp window has focus - but fails otherwise.
So I am looking for a safe way to get hold of the handle to the SketchUp window regardless of whether it has focus or not.
Seeing how GetActiveWindow is able to get the active window for the calling process I was wondering if it was possible to enumerate the windows that belong to the calling process instead. Then I can scan through the results and find my window.
Alternatively, getting the process id for the calling thread, so I can enumerate ALL windows and pick out the one that belong to the thread my script runs in.
Any ideas?

You can use EnumWindows to find all top-level windows. In Ruby, win32-api supports passing in appropriate callbacks.
Edit: You can then use GetWindowThreadProcessId to determine what process each window belongs to.
Edit: To determine the process id of the process running your script, use GetCurrentProcessId.

Related

Why does Spy++ fail with console windows

I was attempting to verify that messages were being sent to my window using Spy++ (running Windows 7), but I mistakingly tried to spy on a console window that my program was using for debug output. Spy++ promptly notified me that "The specified window cannot be spied upon. Windows will not allow access to the message stream for this window."
While Spy++ does correctly gather other information about the window (e.x. name, style, class name), it cannot process the message queue. Why is this? And, out of morbid curiosity, is there a way to prevent Spy++ from accessing the message queue of my own custom window using the Windows API?
While Spy++ does correctly gather other information about the window (e.x. name, style, class name), it cannot process the message queue. Why is this?
The console window belongs to the CSRSS process, not the CMD.EXE process. CSRSS is a critical system service that is protected and cannot be hooked without special debug privileges.
"When a user-mode process calls a function involving console windows, process/thread creation, or side-by-side support, instead of issuing a system call, the Win32 libraries (kernel32.dll, user32.dll, gdi32.dll) send an inter-process call to the CSRSS process which does most of the actual work without compromising the kernel."
And, out of morbid curiosity, is there a way to prevent Spy++ from accessing the message queue of my own custom window using the Windows API?
Typically, no. Unless you manage to run your window in a protected system process.
So, I discovered this myself recently, I created a console .NET application which launches a process using CMD.EXE and I ran into an issue with some Win32 interop around the keyboard. So I broke out the previously trusty Spy++ utility to see what was happening to find that I was completely unable to monitor the message queue for my application from it.
So as per the op's question:
"Is there a way to prevent Spy++ from accessing the message queue of my own custom window using the Windows API?"
There is a list of restricted windows classes baked into Spy++:
SpyxxHk (presumably it's own hooking class),
#32768 (Context Menu),
#32769 (the Desktop),
ttyGrab ,
ConsoleWindowClass (Command Prompt)
So, if you in any way tie your app to these classes Spy++ will display that block message when attempting to watch their messages, of course this may not prove useful since it only restricts those classes.
Referring to MS documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx
"For out-of-context events, the event is delivered on the same thread that called SetWinEventHook. In some situations, even if you request WINEVENT_INCONTEXT events, the events will still be delivered out-of-context. These scenarios include events from console windows and events from processes that have a different bit-depth (64 bit versus 32 bits)"
Suggests it is possible to get console window events.

How to intercept a window message in a shell extension

I have a shell extension that needs to reload its configuration when a specific window message (custom message registered with RegisterWindowMessage) is broadcasted by another application.
I tried several approaches to intercept the message:
Installing a window subclass callback on a window of Windows Explorer, using SetWindowSubclass. This works on Window 7, but not on Windows 8, because apparently DllMain is not called on the main thread, and SetWindowSubclass doesn't work from another thread. This is mentioned in the documentation:
You cannot use the subclassing helper functions to subclass a window across threads
Installing a hook for CALLWNDPROC, using SetWindowsHookEx. Because I don't want to slow down the whole system, I install the hook for a specific thread only (the explorer's main thread). This works on Windows 8, but not on Windows 7... I suspect this is because I'm hooking on the wrong thread, but I'm not sure. And anyway, this approach seems overly intrusive.
Creating a message-only window to handle the message. This doesn't work at all, because message-only windows don't receive broadcasted messages.
Is there a reliable way to receive a window message in a shell extension?
A window message initially seemed to be the easiest way to notify the shell extension, but if you think another mechanism would be more appropriate, I'm open to suggestions.
Create a hidden window and listen for the message in its window procedure.
Register a window class that has default values for all the fields apart from the window procedure and class name. You don't need to specify anything else in the window class since the window will never be visible.
When you create the window, pass 0 for the window style. Specifically exclude WS_VISIBLE.
Pass 0 for the WndParent when you create the window. This will make it a top level window and so eligible to receive broadcast messages.

Detect when a specific process creates a window (on Windows)

I have an application which I automate and run in invisible mode. However I want to detect if that application creates and shows any windows so I can interact (or just hide) them.
I'm looking for a way to get notified by the OS that a window was created by the shell.
(I'm using C#)
This is possible by creating a system wide Windows hook.
Call SetWindowsHookEx with WH_SHELL as the hook id.
In the ShellProc callback function the nCode parameter will have the HSHELL_WINDOWCREATED value whenever a window is created.
Then I can use GetWindowThreadProcessId to check if the window handle provided in the wParam belongs to the process I am interested in.
This must however be implemented in a native dll since .NET assemblies can only implement system wide hooks for WH_MOUSE_LL and WH_KEYBOARD_LL.

Windows analog of _NET_WM_USER_TIME

Is there an analog of _NET_WM_USER_TIME property in Win32 or other way to get list of windows sorted by last used time?
There's the EnumWindows call, which lists all of the windows on-screen at any given time:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633497(v=vs.85).aspx
Secondly, GetActiveWindow will give you the top-level window currently active, and GetFocus the window with input focus:
How can I tell if a Window has focus? (Win32 API)
There's no way to get a list of focus history from the Win32 API - it's a pretty niche bit of information! - but you can run a process on a background thread which periodically iterates through the results of EnumWindows, compares the handle to GetActiveWindow and stores a log over time of windows and focus statuses. That way, you'll be able to interrogate your very own log whenever you want without additional overhead.
I used to do much the same thing from Visual Basic back in the pre .NET days, but the same should be perfectly possible from any other environment which can get to the Win32 API.

How do I provide the "Find Window's Process" feature in Process Explorer (sysinternals)

I'm developing an application for debugging purposes. I want the user to be able to select the process to be debugged using the mouse. Process Explorer does a great job of this with the "Find Window's Process" feature. What I can't figure out is how it does this? Does anyone know the Window's API that provides this functionality?
Thanks, Grant
I haven't tried this, but it should work: Use WindowFromPoint to get the window handle, then use GetWindowThreadProcessId to get the ID of the process that created the window.
Alternatively, you could use EnumWindows to enumerate all top-level windows on the screen, filter them by some criteria (e.g. position) and then use GetWindowThreadProcessId to get the process IDs.
If I understand you correctly you are looking to enumerate all Windows and perform some action when the target Window in question is found. You can do this by enumerating all current windows and then performing some action when the user is over the window in question. You will have to associate that window handle with a process.
This is not a simple task as it requires going through a lot of hoops but it is possible, just have to put all the pieces together.

Resources