Topic: Fix for HIDSharp when it blocks exiting .net app
EDIT: After further investigation I am modifying this and presenting it as a solution rather than as a question.
How can I unblock HIDSharp when an application wishes to exit?
I have a native windows application (not written by me) that is hosting and running a .net dll plugin (that is written by us).
The native app is taking a very long time to shut down.
The native app is MS Word and we are running a .net VSTO AddIn in it.
Eventually MS Word forcefully shuts itself down and will sometimes disable our AddIn as a result on the next time it starts.
Running HIdSharp's DeviceList.GetHidDevices method starts code that prevents shutdown, but calling that method in a .net console app does not prevent the app shutdown.
Debugging HIDSharp it turns out there is a message loop that is started on an invisible window when calling DeviceList.GetHidDevices.
This message loop calls a native method called GetMessage, that blocks the thread that called it until a message is received.
Because the thread is blocked by unmanaged code, even when calling the managed thread's abort method during shutdown the code does not exit the GetMessage call because at the point it is blocked the thread is in native code and is not managed.
A workable solution to the problem is, during out shutdown method's execution, to free the blocked thread my supplying a message to the program. That message is then picked up by the GetMessage.
That in and of itself isn't quite enough though for two reasons:
1.) As GetMessage runs in a loop the message must be of a value that causes the loop to exit (i.e. cause GetMessage to return 0 or 1).
2.) As GetMessage is listening on a specific window the message I send must be to the main program window.
So using the native method PostMessageA in (winuser.h) as follows does the trick:
PostMessageA(hWndOfMessageLoopWindow, WM_QUIT, IntPtr.Zero, IntPtr.Zero);
Using WM_QUIT causes GetMessage to return 0. (This is by design in Windows).
hWndOfMessageLoopWindow is obtained using the native method FindWindow and you pass the class name and window name HidSharpWindowMonitor (which is the class name given to the window in the WinHidManager.cs class)
One plus side to this solution is that it works without any having to make any changes to HIDSharp's code.
However, it relies on knowing HIDSharp's internals (which could, in theory change in the future).
Sending WM_QUIT to this specific message loop window not a problem because it only shuts down that window rather than the application.
It would be much better if HIDSharp offered this functionality itself. But for the time being, this is a good enough workaround.