Find out what process registered a global hotkey?

2019-01-20 22:35发布

As far as I've been able to find out, Windows doesn't offer an API function to tell what application has registered a global hotkey (via RegisterHotkey). I can only find out that a hotkey is registered if RegisterHotkey returns false, but not who "owns" the hotkey.

In the absence of a direct API, could there be a roundabout way? Windows maintains the handle associated with each registred hotkey - it's a little maddening that there should be no way of getting at this information.

Example of something that likely wouldn't work: send (simulate) a registered hotkey, then intercept the hotkey message Windows will send to the process that registered it. First, I don't think intercepting the message would reveal the destination window handle. Second, even if it were possible, it would be a bad thing to do, since sending hotkeys would trigger all sorts of potentially unwanted activity from various programs.

It's nothing critical, but I've seen frequent requests for such functionality, and have myself been a victim of applications that register hotkeys without even disclosing it anywhere in the UI or docs.

(Working in Delphi, and no more than an apprentice at WinAPI, please be kind.)

9条回答
唯我独甜
2楼-- · 2019-01-20 23:05

I haven't been a hard-core windows user for a few years (I switched to Mac). But I used to swear by Process Explorer to find out what process is using a particular file I was trying to delete. Maybe it help find out which process uses a hot key?

查看更多
我只想做你的唯一
3楼-- · 2019-01-20 23:13

Off the top of my head, you might try enumerating all windows with EnumWindows, then in the callback, send WM_GETHOTKEY to each window.

Edit: Apparrently I was wrong about that. MSDN has more information:

WM_HOTKEY is unrelated to the WM_GETHOTKEY and WM_SETHOTKEY hot keys. The WM_HOTKEY message is sent for generic hot keys while the WM_SETHOTKEY and WM_GETHOTKEY messages relate to window activation hot keys.

Note: Here is a program purporting to have the functionality you are looking for. You could try decompiling it.

查看更多
Bombasti
4楼-- · 2019-01-20 23:14

I know you can intercept the stream of messages in any window within your own process - what we used to call subclassing in VB6. (Though I do not remember the function, perhaps SetWindowLong?) I am unsure if you can do this for windows outside your own process. But for the sake of this post lets assume you find a way to do that. Then you can simply intercept the messages for all top level windows, monitor for the WM_HOTKEY message. You wouldn't be able to know all the keys right off the bat, but as they were pressed you could easily figure out what application was using them. If you persisted your results to disk and reloaded each time your monitor application was run you could increase the performance of your application over time.

查看更多
Deceive 欺骗
5楼-- · 2019-01-20 23:20

This seems to tell you a lot: http://hkcmdr.anymania.com/help.html

查看更多
地球回转人心会变
6楼-- · 2019-01-20 23:24

Another thread mentions a global NT level keyboard hook:

Re-assign/override hotkey (Win + L) to lock windows

maybe you can get the handle of the process that called the hook that way, which you can then resolve to the process name

(disclaimer: I had it in my bookmarks, haven't really tried/tested)

查看更多
Lonely孤独者°
7楼-- · 2019-01-20 23:25

After some research, it appears that you'd need to get access to the internal structure that MS uses to store the hotkeys. ReactOS has a clean room implementation that implements the GetHotKey call by iterating an internal list and extracting the hotkey that matches the parameters to the call.

Depending on how close ReactOS' implementation is to the MS implementation, you may be able to poke around in memory to find the structure, but that's over my head...

BOOL FASTCALL
GetHotKey (UINT fsModifiers,
           UINT vk,
           struct _ETHREAD **Thread,
           HWND *hWnd,
           int *id)
{
   PHOT_KEY_ITEM HotKeyItem;

   LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
   {
      if (HotKeyItem->fsModifiers == fsModifiers &&
            HotKeyItem->vk == vk)
      {
         if (Thread != NULL)
            *Thread = HotKeyItem->Thread;

         if (hWnd != NULL)
            *hWnd = HotKeyItem->hWnd;

         if (id != NULL)
            *id = HotKeyItem->id;

         return TRUE;
      }
   }

   return FALSE;
}

I presume this thread on sysinternals was asked by someone related to this question, but I thought I'd link to it anyway to keep the two together. The thread looks very intriguing, but I suspect that some deep dive spelunking would need to happen to figure this out without access to the MS internals.

查看更多
登录 后发表回答