Subscribe to Vista Events in .NET (e.g. Window Opened) - events

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

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.

I have exactly the same issue as this, and I think I have a workable solution. Initially I looked into a similar option to the one mentioned by 'tylerl'. In my case however, instead of using 'SetWindowsHookEx', I attempted to use the similar function 'RegisterShellHookWindows'.
Unfortunately, this only succeeded in providing me with notifications of when a subset of windows are created/destroyed. The only windows which it provided notifications for are those shown on the taskbar.
Since I didn't fancy hacking into other processes, or writing the native code which would be required for SetWindowHookEx, I tried digging into the .NET automation APIs introduced in .NET 4.0, and I think this has the answer to your problem (at least as far as detecting when windows are opened / closed).
Here's a code snippet for using this API to detect windows being opened/closed:
using System.Windows.Automation;
private void StartMonitoringForWindowEvents()
{
Task.Factory.StartNew(() =>
{
AutomationEventHandler windowOpenedHandler = new AutomationEventHandler(OnWindowOpened);
System.Windows.Automation.Automation.AddAutomationEventHandler(
WindowPattern.WindowOpenedEvent, AutomationElement.RootElement,
TreeScope.Descendants, windowOpenedHandler);
});
}
private void OnWindowOpened(object source, AutomationEventArgs eventArgs)
{
try
{
AutomationElement sourceElement = (AutomationElement)source;
string message = string.Format(
"Automation.WindowOpened PID: {0}, Handle: {1}, Name:{2}",
sourceElement.Current.ProcessId,
sourceElement.Current.NativeWindowHandle,
sourceElement.Current.Name);
Debug.WriteLine(message);
// for each created window, register to watch for it being closed
RegisterForClosedWindowEvent(sourceElement);
}
catch
{
}
}
private void RegisterForClosedWindowEvent(AutomationElement element)
{
try
{
string elementName = element.Current.Name;
int processId = element.Current.ProcessId;
int nativeHandle = element.Current.NativeWindowHandle;
AutomationEventHandler windowClosedHandler = new AutomationEventHandler(
(ignoreSource, ignoreArgs) => OnWindowClosed(nativeHandle, processId, elementName));
System.Windows.Automation.Automation.AddAutomationEventHandler(
WindowPattern.WindowClosedEvent, element,
TreeScope.Element, windowClosedHandler);
}
catch
{
}
}
private void OnWindowClosed(int nativeHandle, int processId, string elementName)
{
string message = string.Format(
"Automation.WindowClosed PID: {0}, Handle: {1}, Name:{2}",
processId,
nativeHandle,
elementName);
Debug.WriteLine(message);
}
You will need to add a reference to the assemblies 'UIAutomationClient' and 'UIAutomationClientTypes'.
Here's a link to the MSDN documentation (you'll probably particularly want to take a look at the information on events):
http://msdn.microsoft.com/en-us/library/ms747327.aspx
Important implementation Notes:
1.) Notice that in the sample, I used a task factory to register for reception of the automation events. It's particularly important to avoid using the UI thread when registering for automation events or generally interacting with the automation APIs. Doing so can (and usually quickly does) result in a deadlock. Therefore, I use the task factory to ensure registration is done via the thread pool.
This also means, that the events will be received on the thread pool... So, if you need to perform any UI updates, you will have to marshal these across to the UI thread.
2.) You'll also note, that I capture any needed information on the element which may be closed, at the time of registration (using a closure). This is because, once the element is closed, we will no longer have access to this information - since the element has been destroyed.
Phil

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.

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.

Related

In a Visual Studio Extension, how to detect when the debugger Continues

I need my Visual Studio extension to react to debugging events. I've registered a IDebugEventCallback2 and I'm receiving events, but all I get for each event is an opaque IDebugEvent2 and a Guid, many of which are not only undocumented but don't appear anywhere on the web (or in my registry).
My specific requirement at the moment is to know when the process is Continued - ie. the user has hit Continue, Run to cursor, etc. What Guid should I be looking for?
Or is there some other event family that I should be subscribing to?
(More generally, is there some way I'm missing to find out about the events that are delivered to my IDebugEventCallback2::Event callback, when many of them don't appear in MSDN or anywhere else? Thanks!)
There is no easy way to do this. Actions such as Continue and Run to cursor are abstractions implemented by Visual Studio and do not correspond to any unique event(s) with respect to the debug engine. The debug engine event reporting interface IDebugEventCallback2 will enable you to get notified only on fine-grained events such as when creating a breakpoint or reaching a breakpoint.
While Visual Studio enables you to perform actions such as Continue and Run to cursor programmatically, it does not provide a direct way to get notified when they are taken.
You can use EnvDTE.DebuggerEvents.OnXxx events to get notified when something is about to happen. In particular, the OnEnterBreakMode event enables you to intercept a breakpoint hit and possibly take an action. You can also inspect all the details of the reached breakpoint(s) using the current EnvDTE.Debugger inside the event handler.
Now with some effort, you can use these constructs to implement events that correspond to all Visual Studio debugging actions including Continue and Run to cursor accurately. If you require additional events not provided by EnvDTE.DebuggerEvents (such as when a breakpoint is inserted), you have no choice but use IDebugEventCallback2.Event. In this case if you have specific events in mind, please mention them explicitly and I might be able to tell you the corresponding IDebugEventCallback2.Event GUIDs.
You probably got off on the wrong foot here, the IDebugXxx interfaces were really intended to create your own debugging engine. Still useful perhaps to see what is going on in the existing engine, you are suppose to use QueryInterface() to discover the specific interface that matches the event. Like IDebugEngineCreateEvent2, IDebugProcessCreateEvent2, IDebugProcessDestroyEvent2, etcetera. There are a bunch of them, they are listed in the VSSDK\VisualStudioIntegration\Common\Inc\msdbg.h header and include their IID.
Best thing to do is peek at this sample, it shows how to crack the event notification into the specific interfaces. The AD7Events.cs source file shows the wrappers. Do keep in mind that this sample was made to show how to create an engine, not how to use the one already built into VS.
But yes, you are not going to get a "continue debug" event out of this. A debugging engine does not need that event since it is already responsible for taking care of that by itself. It already knows when it calls IDebugProgram3::Continue().
Surely what you are looking for is IVsDebugger.AdviseDebuggerEvents(). That's the one that tells you what the built-in debugger is doing. You need to pass an object of a class that implements IVsDebuggerEvents, your OnModeChanged() method will be called with a DBGMODE notification. I don't see a lot of fantastic examples that demonstrate usage, this web page might be helpful.

How are Inspect.exe/UI Accessibility Checker causing my program to gracefully resume after null pointer access and what else can I do about it?

The accessible objects in my custom table control are stored in a doubly linked list in the table itself (so they can be invalidated when the table window is destroyed). Right now, my WM_GETOBJECT handler contains the following erroneous code sequence (where t is the table and ta is the new accessible object):
ta->next = t->firstAcc;
t->firstAcc->prev = ta;
t->firstAcc = ta;
This is an error because when the linked list is empty, t->firstAcc will be NULL, so the second line will lead to a null pointer exception.
...except not. When Inspect.exe queries my table's accessible object, it seems to "intercept" the null pointer exception, bringing my program back to a stable state and repeating the process all over again a few times before finally giving up and just grabbing the standard accessible object instead. The program still runs and seems to run quite well!
And it's not just Inspect.exe; UI Accessibility Checker also exhibits this behavior too.
This is Inspect.exe 7.2.0.0 and UI Accessibility Checker 3.0, both running on Windows 7 64-bit. I forget if both came with Visual Studio 2013 Express for Windows Desktop or not (with one of the Windows SDKs instead). The accessible objects are MSAA IAccessible objects because Windows XP compatibility is still required.
Obviously this makes debugging bugs like this problematic. So my questions are simple:
How are Inspect.exe and UI Accessibility Checker doing this? Is it special code that they share or is there something about MSAA or OLE or COM that does this?
Is there anything I can do about this? Neither of these programs have options to turn off the behavior. Could I just get the accessible object myself (posing as a client) to test this behavior? (That would work for the top-level object, but doing thorough tests for navigation would be a bit more painful.) And if so, would I need to initialize COM (for something in the same process) or run as administrator (because of UIPI)?
Thanks.

InvokeMethod of Windows Workflow 4 can encounter Exception C0000005

Thank you for reading at first.
I designed a WPF application which rehosted the Designer, Toolbox and Properties of Windows Workflow. My Idea is really simple that I just want have visualization at runtime about my workflow and design them in the runtime as well.
ISSUE:
Now I try to Invoke a Method of a class under the same namespace of whole application. The class is called MyTwsClass. Please have a look below:
It is extremely Simple. The TwsClass is from a Reference ActiveX of Interactive Brokers Trading Software. This ActiveX simply provide the method and event for you to communicate with your account. Alright, I implement the MyConnect() method as you can see and this method simply set up some string and int variables to be parameters of connect method from TwsClass. I noticed that I could not set MyTwsClass or MyConnect method as static.
Now, at runtime designer, I try to invoke the MyConnect method. First of all, picture below:
Since MyTwsClass could not be a static class with static method (I guess it is because it inherits from the ActiveX class TwsClass, I am not sure as a newbie.) So I wanna invoke the instance method. It has no complaints before running the workflow. After running this, I expect that I should be able to connect to the API of the trading software.
Now I run the workflow:
Right after clicking the running button, it runs and I got pop up window to tell me that APP has crashed with exception code C0000005. If I click the close option, my WPF application will be closed. BUT before I close it, I could see that ACTUALLY the crashed WPF actually connected to the API as you can see in picture above to tell me that 1 is connected......
I tried my best to check this problem on Internet. I am kind of have sense that it is all because of some issue within Interop or COM process between my WPF and the reference ActiveX as the crash window indicated that the TwsSocket.dll is the reason.
But I really could not figure out further.....

Crash after the second RichEdit initialization in x64

According to Using Rich Edit Controls I use RichEdit in such way:
MyControl::OnCreate()
{
handle = LoadLibrary(_T("Riched20.dll"));
}
MyControl::OnDestroy()
{
FreeLibrary(handle);
}
It works fine for win32 but recently I’ve built x64 configuration and now my control fails after the page reload.
I’ve noticed that if do this:
MyControl::OnCreate()
{
handle = LoadLibrary(_T("Riched20.dll"));
FreeLibrary(handle);
handle = LoadLibrary(_T("Riched20.dll"));
}
everything works fine.
I don't wish to put this code into production, so is there any suggestions about better solution/workaround?
Since the reported fault module is Richedit20.dll_unloaded it means you are unloading the DLL while code from it is still in use.
For example, if you still have a richedit window open when you (completely) free the DLL, you can see crashes like that as soon as anything triggers a call to the control's window-proc. This is because the control's window-proc was inside the unloaded DLL code.
It should be safe to call LoadLibrary and FreeLibrary multiple times (so long as the calls balance out), so I doubt that is the problem. It may just be triggering the problem. Also, the problem was there in 32-bit builds; you just got lucky and never triggered it.
OnDestroy is the wrong place to call FreeLibrary. There are several window messages which get sent to a window after WM_DESTROY (e.g. WM_NCDESTROY).
Child windows also still exist when OnDestroy is called. If the richedits are children of your control (rather than the control itself) then moving the FreeLibrary into OnNcDestroy may save you. (Child windows are destroyed by the time WM_NCDESTROY is called.) I'd still say it's not a good place to free the library, however.
So you definitely want to move your FreeLibrary call. I would move both it and the LoadLibrary completely out of the control itself. It's not normal to have controls which load/free libraries whenever an instance of them is created. Instead, have some static init/uninit code somewhere which loads the libraries you need once and for all and frees them when the application is shutting down.
(If your app only rarely uses the control then it might make sense to load/free the library only when windows using the control are active. That situation is rare, though. Usually you're better off just leaving the DLL loaded.)

How can I get the name of a Visual Basic control given its HWND?

I'm working on a little macro record/replay tool which can automate a few very old Visual Basic 6 GUIs we have. To do so, I'm identifying the controls by their name (the value of the name property of a control, that is).
One part of this tool needs to determine the name of a control given its HWND. For newer Visual Basic applications which were done using VB.NET, I can use the WM_GETCONTROLNAME window message. This works nicely.
However, this message is not understood by older windows. Is there any way to do this for controls of Visual Basic 6 applications? A solution which does not require being in the process of the GUI would be preferrable, but if I had a solution which only works inside the GUI process then that would be acceptable as well (since I can do the injection myself).
UPDATE: One thing I just tried, this moderate success: I used the AccessibleObjectFromWindow to check for implementations of the IAccessible interface of the object which shows the given HWND. In case I get an implementation (it seems that many [all?] Visual Basic controls implement this interface), I use the accName property to read out the "accessible name". Sometimes this does yield a useful string, but usually it doesn't.
I believe the only way would be getting inside the process and obtaining a pointer to the Form object, yet I have no idea how to do it from outside.
Is it possible you add support for the WM_GETCONTROLNAME to those older applications?
Or maybe, you could identify the controls by some other, natively-available properties?
Other that that, as Raymond is saying, there isn't much you can do.
Can you modify the vb6 apps? if so in each form load event you could iterate me.controls and use the SetProp(ctrl.hwnd, "MYNAME:" & ctrl.name, 0) api to add the name to the window's own property list, then in your other app you can EnumProps(ctrl_HWND) looking for the one that begins with MYNAME: and parse out the value.

Resources