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.
I've assembled my new PC yesterday, and I've decided to give Windows 8 a try. However, today, during the debugging of moderate Qt application, debugger yielded "Invalid Binding Handle" error message on a pretty simple line (it was line that is auto-generated by Qt's moc.exe:
// QWebView *view (...)
view->setUrl(QUrl(QString::fromUtf8("about:blank")));
// Failing in setUrl call, not in QUrl constructor, or in fromUtf8 function.
However, running this application without debugger works just fine, both in Release and Debug versions.
I've got some clues on the internet to enable Terminal Services, but it seems that there is no such service in Windows 8.
Does anybody have any clue what should I check?
Edit
Moving the widget into other application yielded no error, so apparently, widget (which is pretty small - just QWebView and QProgressBar) is fine. But, when I show this widget in my main function:
QApplication app(argc, argv);
MyWidget w;
w.show();
return app.exec();
it is still failing with the same error. Examining call stack (which is not very helpful when error appear) and stepping into function calls, I've tracked error down to retval = HeapFree(_crtheap, 0, pBlock); in function _free_base, in file free.c And it seems that function is called from dbgdel.cpp, function _free_dbg( pUserData, pHead->nBlockUse ); and it is called from unlock() function.
Attaching the debugger to already active process is still yielding the same error.
I am linking a lot of 3rd party libraries here, so I will try without them, as I'm run out of ideas...
Edit 2:
If I pass this exception to the program, it seems to be running fine.
Edit 3
Commenting setUrl line raises the same exception somewhere in QWebKit, where strdup function is called...
Well, this was easy, but it took me two months to solve (while ignoring the error in the meantime).
This was not an unhandled exception - this was handled exception, and stepping into assembly code and watching the stack frame told me that this exception was handled.
Then I remembered that I've set debugger to break when all C++ and Win32 exceptions are raised. Resetting the debugger settings removed the issue.
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.)
I'm trying allow drag and drop to the tray icon on my application.
I know it's impossible to do this with the higher level C# WindowsForms API, since NotifyIcon doesn't support drag events.
So with a little help of a more windows-experienced friend I set out to try this via Win32 API. The idea was registering a hook in the tray window handler (after setting DragAcceptFiles(hWnd,TRUE); on the "SysPager" window handler).
The hooking and dropping part is working from the tray to the DLL.
LRESULT CALLBACK myHookProc (int code, WPARAM wParam, LPARAM lParam){
if (code == HC_ACTION)
{
PMSG msg = (PMSG) lParam;
switch(msg->message){
case WM_DROPFILES:
::MessageBox(NULL, L"Dropped files!", L"Test", MB_OK);
// call my app's registered hook
break;
}
return CallNextHookEx(oldHookProc, code, wParam, lParam);
}
As expected I get the message box popping up.
The problem is that I now need to call a function on my C# (WindowsForms) application to notify of this event. Here's where I ran into brick wall.
When I register the callback from my application in the DLL, I store it; but when myHookProc is called, it's value is NULL.
Turns out I was misunderstanding how DLLs work; there isn't a shared instance between my application and the tray area (they're copied or each has its own "instance" if you could call it that) so I can't use any static variables or anything like that to hold the callback reference back to my application.
Spent a couple of hours investigating this and the only solution seems to be shared memory (tried the #pragma data_seg I ran into in some forum, but to no avail), but it starts to feel too much of an overkill for such a "simple" use case.
So the million dollar questions are:
Is it really necessary to offload the hooking to a DLL?
Do I really need to resort to shared memory to accomplish this?
(Bonus question) WM_DROPFILES only works for files; how can I get a drop event fired for text?
Please keep in mind this is my first shot with .NET, C# and Win32 (less than a week); detailed answers explaining why - rather than just stating - will be greatly appreciated!
Thanks.
Yes, you really need to do those things because the window is owned by another process. Global hooks require a DLL that can be injected. Full D+D support requires RegisterDragDrop and COM code. Icky COM code.
And no, you really should not do this because somebody else might have already had the same idea as you. And got his program shipped first. The appcompat team at MSFT must have a nightmare with it. Careful with Raymond Chen, he's got a Bad Temper.
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.