views:

100

answers:

3

Hi, I am trying to build my own little toolbox for Vista.

One of the features is a "window placeing tool" which places the windows at saved position. Another tool I could imagine are extensions to firefox or thunderbird...

For these tools to work, I need them to be able to capture "Events" in Vista. To give you a concrete example:

  • Explorer Opened New Window
  • User started Firefox
  • Mouse moved

For the mouse case, there are some examples for C#. I also know about the directory watcher, nice little helper.

Want I now need is the "new window opened event"

Any idea how to monitor this, without iterating the current window list every 5 seconds (I already know how to get Windows using the DLLImports, and getting Processes using managed code. But I have no Event when the explorer process opens a new windows)

Thanks for your help, Chris

A: 

The answer is not C# (or .Net) specific. You'll need to call SetWindowsHookEx( WH_CBT, ... ). This will allows to know when a window is created, destroyed, moved, sized, etc. You'll also need to get the relevant information from the window to identify if its one you need to do something about. Perhaps GetClassInfo, GetWindowLong, and GetWindowText.

The problem with the SetWindowsHookEx is that in order to get events from every window you need to have a separate win32 dll with the function in question exported. Although you might have success with the procedure outlined here.

Joel Lucsy
A: 

To expand upon Joel Lucsy's answer, you need to use the Win32 API. However, there's a nice library, the Managed Windows API, that provides an object-oriented wrapper over common APIs. It may have what you need.

Matt Olenik
Thanks, very nice library. Will definitly look into that, too. Wish I knew it yesterday, 90% of my code is already in there. But hey, learning by doing :-)
+1  A: 

What you're talking about doing is not simple by any stretch.

You're going to need to register a hook, and you're going to have to build a callback procedure that gets called within another process's execution context -- this is not going to be .NET code (probably C instead), and will have to be in a DLL. That callback procedure will get called every time a certain class of events happens. It will examine the events it receives and filter out the ones you're interested, then send your application the notifications you want (probably via PostMessage). You'll then tap in to your application's main message loop to intercept those messages, and from there you can fire a .NET Event, or whatever you want.

Writing hook callbacks is tricky stuff because the code gets run within another process, not your own, and the memory management and concurrency issues take a bit of forethought. For that same reason, it's not going to be done in C#. Ideally, though, this callback code will be very small and very fast, since it's going to get called so often.

Also note that while perfectly "legal" in Win32, these system hooks have an immense amount of power and are commonly used by malware to change the way your system works. For that reason, you may run afoul of antivirus software if you attempt to do this sort of thing on a customer's computer.

Also note that the far-reaching effects of system hooks also means that simple programming mistakes can take down your whole system, which you will probably discover for yourself at some point while debugging; so save everything before you hit "run".

Good luck!

EDIT

Did a bit more search to see if there's any way to write the hook proc in C#, and came up with this:

How to set a Windows hook in Visual C# .NET

This is almost what you're looking for, but not quite. Hook procedures can either be global (which means that they run on every application) or thread (only runs within your application). The document states that:

Global hooks are not supported in the .NET Framework

Except for the WH_KEYBOARD_LL low-level hook and the WH_MOUSE_LL low-level hook, you cannot implement global hooks in the Microsoft .NET Framework. To install a global hook, a hook must have a native DLL export to inject itself in another process that requires a valid, consistent function to call into. This behavior requires a DLL export. The .NET Framework does not support DLL exports. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically.

Which means, again, to monitor things that go on outside your application's view, you need to set a global hook, which can't be written in .NET.

tylerl
Thanks a lot for your detailed answer. I think I will stick to the monitoring solution instead. I most cased, I will tell my tool to open some "set of windows", so I know to scan for open windows afterwards. I think I will even do this by default, by attaching some shortcuts keys to my "workbench layout".Perhaps additionally, I scan every five seconds if there are new explorer windows. Have to check memory impact, but should be negligible.Thanks a lot for the info..Chris