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.
Related
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.
Working in a plugin architecture (specifically, Sparx Systems Enterprise Architect), which does not forward either raw or cooked keyboard events, keyboard shortcuts for the plugin can be defined using RegisterHotKey(). These hotkeys are global, and the registration call fails if the specified key combination is already registered.
Since the application within which the plugin executes can be run in multiple instances, the hotkeys need to be repeatedly registered and unregistered based on which instance is in the foreground. An event hook for EVENT_SYSTEM_FOREGROUND can be set up for this purpose, but the question is: is there a guaranteed delivery order?
I need the instance that is losing focus to be told first so that it can unregister the hotkeys before the instance gaining focus tries to register them.
Is this possible? Or will I have to implement synchronization to be sure?
Windows DevCenter WM_ACTIVATE message says
..Sent to both the window being activated and the window being deactivated. If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the top-level window being deactivated, then to the window procedure of the top-level window being activated. If the windows use different input queues, the message is sent asynchronously, so the window is activated immediately..
So if all of your windows come from the same application sharing the same input queue then it should be guaranteed. I guess that the EVENT_SYSTEM_FOREGROUND is built on top of the older code following the older logic (at least the implementation in ReactOS at http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/focus.c?view=markup (see EVENT_SYSTEM_FOREGROUND inside co_IntSetActiveWindow) does it)
Your problem might be easier if you'd monitor only keyboard events in your original hosting process (no global side effects) using the Windows DevCenter SetWindowsHookEx function, filter WH_KEYBOARD
In that case your code would exist once in one exe having one global variables, no cross-process synchronization would be needed
I need to write application A, which intercepts the WM_ACTIVATE message to a window of application B in order to prevent B from becoming top-most application.
Is it possible to do this without DLL injection (add a hook on that message, process and "neutralize" it with a series of WinAPI calls) ?
I think this is what you're after:
LockSetForegroundWindow
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633532(v=vs.85).aspx
Remarks
The system automatically enables calls to SetForegroundWindow if the user presses the ALT key or takes some action that causes the system itself to change the foreground window (for example, clicking a background window).
This function is provided so applications can prevent other applications from making a foreground change that can interrupt its interaction with the user.
Just don't forget to unlock :)
Edit:
Try SetWinEventHook as described here:
Is there Windows system event on active window changed?
Then when the unwanted window comes to the front you can send it to the background.
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.
Using WinXP. What I need to do (pref in VB or c#) is to detect when another (closed source) program displays a notification balloon in the tray - and grab the details. Any help would be appreciated. Thanks
In similar situations, I have used the Microsoft tool Spy++ to grab the window information and then uses pinvoke calls to FindWindow to detect when the window is present.
I've not tried with a notification balloon, but I imagine that a pinvoke call to GetText would retrieve the contents.
I think you'll need to use pinvoke to do this from a .net language.
On the system I'm using now (Vista Business SP2), balloon windows always seem to have window class #32769 (reserved for desktop windows) and the windows style bit TTS_BALLOON set.
The following might work: Determine the parent window for all notification balloons by creating a temporary one, getting its hWnd, and calling GetParent() before deleting it. You could then periodically poll the children of this parent hwnd (using EnumWindows() or FindWindowEx()) looking for windows with the required class and style.
This seems highly non-portable to me, and likely to require a lot of testing on a variety of platforms.
pinvoke.net and spy++ might be useful.
Good luck!
You will definitely need to use Win API calls to achieve this. If this is the only thing you're trying to do, you'd be better off using straight C or C++ so you don't have to do a bunch of platform invoke for C# or VB.
Since andyjohnson identified that the window class for all notification balloons is #32769, and that they have the TTS_BALLOON style set, you could use a CBT hook (if you're not familiar with Win32 hooks, you might want to read up on them), to get a callback whenever a window is created, and check for windows of that class and with that style.
I'm not sure, though, if a new balloon window is created for second and subsequent popups or if the same one is just hidden and reshown. If this is the case, you might need a CallWndProc hook, to get WM_SHOWWINDOW messages.
Edit:
I should mention that the hooks that I've mentioned cannot be implemented in .NET. Except for the low-level keyboard and mouse hooks, global system hooks must be implemented in a native (unmanaged) DLL. Windows will load this DLL into other processes, and if a managed DLL gets loaded into a process that doesn't have the .NET CLR loaded, it will crash that process. (Even if the CLR is loaded, it might be at a different address, also causing a crash.)
So you must build your hooks in a native (unmanaged) DLL. It's possible to interface from here to a managed application, such as Michael Kennedy has done on Code Project, but to do it properly, and handle the hook types I've mentioned above, you'd need to use interprocess communication, a step that Michael Kennedy left out. All in all, for the purpose you've described, it would probably be easier to just build the whole thing in native code.