Ah, virtual machine/native code interoperation. Hmm.
*researches*
*researches*
*researches*
Okay so! I'm sure I could, but I'm also about 80% sure that you don't have to, and about 90% sure that there's a cleaner way.
The first thing you should know is that, even from managed code, you
can call and use
SetWindowsHookEx(); you're just limited to three of its possible hook types. The good news is that two of those hook types â€â€
WH_MOUSE_LL and
WH_KEYBOARD_LL  are exactly the ones that you want. All you need to do to use these is to make sure that you stick the delegate you're using in a
Pinned GCHandle, then pull an exportable
function pointer out of that delegate to pass to SetWindowsHookEx(). You'll need to catch
WM_LBUTTONDOWN (trivial) and ... at least a)
WM_KEYDOWN on the Esc key when Ctrl is pressed, and b)
WM_KEYUP on the Windows keys most of the time (see below).
This person has been able to do at least some of that — from C#, no less!
... or just use
this library. Yay, open source!
Note that when you're catching the Windows key, you do need to be careful only to catch keypresses that are
not due to the Windows key being used as a modifier. (For example: hold the Win key, press E, then release the Win key. Fortunately, Windows itself treats things like <Win+,> as just <,> so you don't need to worry about whether or not a given key combination is
really a modifier-key combination.) This is not difficult but needs to be noted. (You may have already realized this; if so, I'm just babbling, and hopefully
someone finds this interesting.)
The 20% uncertainty in this approach comes from at least two separate issues. Firstly,
WH_MOUSE_LL and
WH_KEYBOARD_LL are listed as "Windows NT/2000/XP" in the MSDN page for SetWindowsHookEx() (linked above). However,
Link Removed - Invalid URL seems to imply that he was able to use those flavors of hook in Vista as well, so I suspect it's merely the case that the documentation needs to be updated. Secondly, there may be other, more interesting ways to trigger the Start Menu of which I'm not aware. (
WM_COMMAND +
BN_CLICKED, anyone?)
If either of those points fail, the possibly-cleaner fallback method is to write a very small unmanaged DLL (written in C++): call it CSBootstrap.dll. CSMenu.exe is then just a stub executable which injects CSBootstrap.dll into explorer.exe. When injected, rather than loaded normally (and DllMain can tell the difference), CSBootstrap.dll loads up CSMain.dll — the
managed library, written in C#. CSMain.dll then hooks into Explorer.exe's message queue -- it can do this with any hook-type because it's now executing in the context of Explorer.exe -- and pins itself in place using LoadLibrary(). As CSMenu.exe exits, CSBootstrap.dll and its hook procedure get unloaded, but CSMain.dll remains where it is.
Voilà! After an almost Byzantine setup process, you now have nothing except a managed DLL executing directly in Explorer.exe's process space, capable of using SetWindowsHookEx() normally as though there were nothing interesting about it.
If I've missed anything and neither of those are possible, then yeah, basically what you just said. It'd still be a DLL executing directly in Explorer.exe's process space, though.
P.S.: there isn't a documented way to extend Explorer's functionality via COM+ interop, is there? That would be
so much easier, but I haven't the slightest idea where to start looking.
P.P.S.: if you post a
WM_CLOSE message to the taskbar, you get an old-style Shut Down dialog. (See attachment.)