Why is there sometimes a long delay between pressing a hotkey for a shortcut and opening the shortcut?


Via a customer liaison, we received a problem report from a customer.

The customer is facing issues with delayed desponses to opening a .lnk file by pressing its keyboard shortcut hotkey. This delay does not appear when the shortcut is double-clicked.

For example, the customer has created a shortcut to Notepad and assigned it the shortcut Ctrl+Alt+X. Pressing the keyboard combination sometimes takes 5 or 6 seconds for Notepad to open. As noted above, double-clicking on the shortcut causes Notepad to open without delay.

This issue is not consistently reproducible, but it appears to be independent of the shortcut file itself. Any shortcut with a hotkey exhibits this problem.

All the shortcuts in question are on the desktop.

The short answer is "There is a program running on your machine that occasionally stops responding to messages. If you press a shortcut hotkey during those moments, you will experience this problem. Identify the program that stops responding to messages and fix it."

Okay, that sort of cuts to the chase, but the interesting part is the journey, not the destination.

First, observe that if you associate a hotkey with a shortcut to say Notepad, and you press the hotkey twice, you do not get two copies of Notepad. The first time you press the hotkey, Notepad launches, but the second time you press the hotkey, focus is put on the existing copy of Notepad. This is one of those things that's so natural you may not even realize that it's happening.

When you press the hotkey assigned to a shortcut, Explorer receives the hotkey and needs to decide what to do about it. Before it can launch the shortcut, it needs to see if the shortcut target already has a window open, in which case it should just switch to that window.

Finding out whether a window has a hotkey is done by sending the window the WM_GETHOTKEY message. When you press a hotkey that is assigned to a shortcut, Explorer goes to all the windows already on the screen and asks each one, "Hey, what's your hotkey?" If any window says, "My hotkey is Ctrl+Alt+X," then Explorer says, "Oh, sorry to step on your toes. The user pressed your hotkey, so here, go ahead and take focus."

If no window cops to having Ctrl+Alt+X as its hotkey, Explorer says, "Okay, well, then I guess I have to make one." It launches Notepad and tells it, "Oh, and your hotkey is Ctrl+Alt+X."

If there is a window that is not responding to messages, then when Explorer asks it, "Hey, what's your hotkey?", the window just sits there and doesn't answer. After about three seconds, Explorer gives up. "Yeesh, I was just asking a question. Don't have to give me the silent treatment."

And that petulant window is the source of the 3-second delay. It takes Explorer 3 seconds before it finally gives up and says, "Forget it. Even if that was somebody's hotkey, they're being a jerk, so I'm just going to pretend they didn't have a hotkey. Let me open a new window instead and just deal with the hotkey conflict."

Comments (51)
  1. Brian says:

    I'm sure it's too late to change now, but why didn't explorer originally store the hotkey information internally?

    [Because RegisterHotKey is a window manager feature, not an Explorer feature. -Raymond]
  2. skSdnW says:

    And how does the process responding to WM_GETHOTKEY know which shortcut hotkey a user has assigned? My guess is STARTF_USEHOTKEY in STARTUPINFO…

  3. Adam Rosenfield says:

    Whoa, why does the STARTUPINFO struct overload the hStdInput member to be used for either the standard input handle or the wParam value sent with the WM_SETHOTKEY message depending on the flags?  Why not have a separate member for the latter?  How would you launch a program that needed to handle hot keys like this but also redirect its standard streams?

  4. henke37 says:

    And now for the million dollar question, how to hunt down the offending process?

  5. henke37 says:

    @Adam R

    There is no meaningful standard input stream if you were launched with a hotkey.

  6. Tim Dawson says:

    The time delay needs to be shorter. I encounter this all the time when debugging, because usually when broken into the debugger, there is of course a process that isn't responding to messages. And when debugging, I often need to launch shortcuts to handy things like Notepad. This seems to be the same with the Run dialog too, which I'm in the habit of using to launch URLs.

    You've done a great job of explaining why it isn't technically broken, but the user is always right, and it still needs to be fixed.

  7. Paul says:

    Raymond, I appreciate the way you illustrate the way things work by personifying processes, API functions, etc. It really makes it easier to understand.

  8. Adam Rosenfield says:

    @henke37: How so?  What if I want to write a program that launches other programs with hot keys, and what if one of those programs is one that has a UI but also reads debugging commands from standard input?

  9. Eric Fournier says:

    @Adam Rosenfield

    It seems a mite contrived to think that you would like to have a program launch other programs through hotkeys rather than the normal API for doing it, such as CreateProcess.

  10. Rick C says:

    @Tim Dawson "You've done a great job of explaining why it isn't technically broken, but the user is always right, and it still needs to be fixed."

    No, this is not the case at all.  Imagine if Microsoft tried this.  The most obvious "fix" is to reduce or remove the delay.  Now you'll have users saying "sometimes my shortcuts don't work at all" if their program happens to not respond to messages for just longer than the delay.

  11. Adam Rosenfield says:

    @Eric Fournier: I am talking about using CreateProcess to launch other programs.  I was positing that a program could want to launch other programs with CreateProcess and passing in STARTF_USEHOTKEY|STARTF_USESTDHANDLES as the dwFlags of the STARTUPINFO passed to CreateProcess.  It's a little contrived but not entirely out-of-this-world, IMO.

    It seems to me that the STARTF_USEHOTKEY flag exists for the convenience of the window manager — assuming that the window manager is the only system that uses it, it makes sense that it doesn't need STARTF_USESTDHANDLES to redirect the standard streams of a process launched with a hot key.  If the window manager ran in kernel mode, that flag wouldn't need to exist, and it could do all its magic inside kernel mode without exposing that flag to the userspace API.  But since it runs in user mode, that flag needs to exist in user mode, and if other programs want to implement their own hot key launching, then why not also let them redirect the standard streams at the same time if they want?

  12. aux says:

    That explains the shortcut delay problem I had a while ago. I could never figure out where the delay comes from, and ended up just not using hotkeys anymore. Is there a way to make it just ignore running applications and always launch the shortcut no matter what?

  13. Mike Mol says:

    @Rick C: No, because the message was still placed in the application's message queue, and it'll receive the message when it eventually gets to that point in its queue. (Unless there's some kind of transactional logic for applications' message queues I'm not familiar with.)

    You're more likely to see a complaint of 'sometimes my hotkey starts a new copy of the application, but sometimes it causes the existing copy to gain focus.'

  14. jmthomas says:

    Another "local solution to a global problem".  Keyboards, shortcuts, and shortcut keys are global.  Window manager is not global.  In a ringed kernel, there would be a place (API + structures) for global support of shortcuts.

  15. @HiTechHiTouch: I agree, the window manager isn't global, because there are processes that don't use it. But neither are keyboard shortcuts, because the very same processes that don't use it (services, system processes, etc.) do not communicate with the user or are even launched by him/her. So in the end, it's a local solution to a local problem.

    @Adam Rosenfield: For a similar reason, I don't think it's useful to support both standard input and keyboard shortcuts: if the process is launched via a keyboard shortcut, what console or handle does its input get attached to? And if the process is being launched by another process so it can attach to its standard input (say, cmd.exe or a debugging host), does the keyboard shortcut parameter make any sense? Will it ever need to respond to a shortcut?

  16. doug.kavendek says:

    I would also be interested in knowing if there's any way to force it just to always launch the shortcut, since for me when I press the shortcut key twice I really want it to run twice — like opening up two separate ssh windows.  If it's an app that I want to force only a single instance, I can generally configure the app itself to do its own check.  I've usually just made intermediate batch files to circumvent the single-instance check, but the huge delay while debugging is still one of those recurring minor pains.

  17. Mason Wheeler says:

    >I'm sure it's too late to change now, but why didn't explorer originally store the hotkey information internally?

    [Because RegisterHotKey is a window manager feature, not an Explorer feature. -Raymond]

    OK, that just moves the problem around a little.  I think the real question is, why do you have to query active programs for their hotkeys?  Why doesn't the program register its hotkey with [some global location] when it's launched, and then Explorer can query that, so it doesn't have to deal with unresponsive programs?

  18. AndyCadley says:

    @henke37

    And now for the million dollar question, how to hunt down the offending process?

    You already know the answer. Write a program that mimics Explorer's behaviour and note which processes don't respond in 3 seconds.

  19. Roger says:

    The latest version of Android has a setting in the developer section where you can make apps that don't respond in a timely fashion in their main thread to messages flash.  You get a thick red border appearing around the app until it responds to the message.  It is notable how often it happens even on apps written by Google.  (The time threshold is also considerably less than 3 seconds.)

  20. Very good explanation, thanks.

    Would parallelizing the code in Explorer that does this scan help? This way, you could ask a bunch of windows at the same time and hopefully the right one will come back right away and you don't have to wait for the slow ones.

    [That only speeds up the case where the app is already running. The initial launch will still have to wait. -Raymond]
  21. Adrian says:

    I keep wondering why it seems to be worse with Windows 7 than it is with Windows XP.  With no applications running, my Windows XP box will respond to the Windows+L hotkey to lock the screen instantaneously, but my Windows 7 box often takes three or more seconds.  It's weird because, in general, the Windows 7 machine feels much snappier, which is not surprising since the hardware has much more horsepower.

    I assume screen lock go through the same procedure as other hotkeys .  ALT+TAB never seems to stall.  I wonder what other causes there are for slow-responding hot keys.

  22. Ben says:

    >> Would parallelizing the code in Explorer that does this scan help?

    [That only speeds up the case where the app is already running. The initial launch will still have to wait. -Raymond]

    Yes, but it would bring the total down to 3 seconds, as opposed to a cumulative total of n*3. Which happens to me a lot. (not just hot keys, also the DDE open/print verbs)

    [True. Or apps could stop going unresponsive. -Raymond]
  23. jd says:

    My workaround is to use a program (such as AutoHotKey) that allows you to configure hotkeys but doesn't bother to query apps/windows.  You can optionally add app detection logic to prevent a duplicate instance, but control over this is in your hands.

  24. Brian Friesen says:

    This answers a long standing problem of mine.  I've noticed if Visual Studio is actively debugging another process and I try and use shortcuts, there is a long delay (sure feels longer than 3 seconds, maybe it's 3 seconds per non-responding app).  It's very annoying and I've always wished Explorer were changed to prevent this.  On the one hand it's frustrating because I'm interrupted trying to launch a program just because another process is not responding.  Well at least knowing *why* this happens makes it a little easier the next time it happens to me.

  25. Anonymous Coward says:

    A similar problem can happen when you double click a document, or click on a link in an HTML control. In that case, in order to prevent the same document being opened twice, a DDE message is sent and if some windows are unresponsive then you get a very annoying delay, which can in some cases even lock up the application which originated the DDE message.

    There are two real flaws here. 1) There are applications which don't respond to their messages. Sometimes there is no real replacement for these and can't count on the developers fixing it. 2) Two applications (in the case of the article Explorer and the hotkeyed application) have a problem to solve, and in order to do so they require cooperation of every application on the system. It's the infamous global solution to a local problem.

    I must confess that I find it really hard to think of a fix. The design is really flawed, but it's there and it must remain working, so changing over to a better design may not be possible. As a start, note that windows generally don't handle WM_{G|S}ETHOTKEY and if they do this results in aberrant behaviour; they just pass it to DefWindowProc. So you could make the window manager handle the messages instead and then the hanging window won't even get the message and can't clog up the system.

    The DDE problem is harder to solve. You can't use PostMessage because you need to know if no one responds, although part of the problem (hanging initiating application) can be mitigated by updating the documentation of ShellExecute[Ex] to warn about the problem of unresponsive windows and what to do about it. Still, all you can do is pass SEE_MASK_NOASYNC or not. Unless you have no UI, you can't pass it (because then you're at the mercy of other applications) but if you do pass it there is a risk your application might exit before the conversation is finished, so you really always have to call ShellExecuteEx on a separate thread with SEE_MASK_NOASYNC and make sure your application will wait on such threads in the case of process exit. Since that's the only correct way of calling it, there should be a flag to make the function do the work for you.

    But this doesn't solve the second half of the problem: no appropriate DDE server is running and a window is unresponsive. You can't really know if the unresponsive window might be the server you're waiting on, and if you shorten the delay you'll get misbehaviour in case when the application is trying its very best to respond but simply can't because of some performance issue (which may be caused by another application). And this puts us in a pickle since DDE servers don't have to report to a central manager that they're running a server, which is a situation inherited from Windows 3.1 and a real weakness of the design. Still, the loword of lParam is supposed to be application specific, so once an application responds, you only have to query that one in the future. This doesn't help when the application name is NULL (for example when the topic is WWW_OpenURL to open it in the default browser) but on the other hand ShellExecute[Ex] knows what the default browser is, I should think.

    There are probably situations where these solutions won't always work right, so it'll need a bit more work, but it could improve the majority of actual use cases.

    Looking back, I realise that this was an enormous wall of text. My apologies.

  26. 640k says:

    Is a full fledged window manager a requirement for using the keyboard now?

    Why the need for apps to register keyboard shortcuts, when USER not keeping track of it anyway?

    [I don't understand the question. USER *is* keeping track of it. Hence the WM_GETHOTKEY message. -Raymond]
  27. cheong00 says:

    @Tim Dawson: Or Windows should change the handling a bit… Explorer can send the WM_GETHOTKEY as broadcast message, and if no reply in 3 seconds, launch the application instead. So in the end it would be juat a little more than 3 seconds delay. (Any application that's busy at that time will be treated the same as not hearing that message)

  28. cheong00 says:

    @James: There's one flaw on that: Not every Windows application is launched by Explorer. Say, IE can launch notepad or else for opening downloads. So Explorer don't keep track of every application opened in the current desktop.

    Maybe it's time to add another Windows message, something like WM_PROCESSSTART. Maybe it can help solve another common problem too. Something like want to launch an application and wait until it's completely loaded to return.

  29. James says:

    @cheong00: That's exactly what I meant by "a case where the window was created by a child process".  My point was that figuring out which window corresponds to which shortcut is very non-trivial, and "storing hotkey information internally" doesn't solve that.

  30. cheong00 says:

    On the other hand, maybe DWM can expose a function to allow Explorer query that, so Explorer can query a centralized source instead of asking each applications?

    It'd be good if Explorer can know when a new application registered new hotkey (maybe through event subscription to DWM), so Explorer will ask what hotkey is registered to that application.

  31. None says:

    What if two windows have the same shortcut?  Which is given focus?

  32. Joshua says:

    [That only speeds up the case where the app is already running. The initial launch will still have to wait. -Raymond]

    Doesn't this also speed up when there's *two* slow windows, or am I missing something here?

  33. steven says:

    This bites me quite a lot. Maybe now I can figure out what program is causing this. Still, I find the behaviour rather annoying as, in almost all cases, I actually *want* to start another copy of the program for which I'm hitting the hotkey. I don't suppose that is configurable?

  34. TejasJ says:

    Thanks for this wonderful explanation..!

  35. Jon says:

    Raymond, I couldn't have put it better than Mason Wheeler:

    I think the real question is, why do you have to query active programs for their hotkeys?  Why doesn't the program register its hotkey with [some global location] when it's launched, and then Explorer can query that, so it doesn't have to deal with unresponsive programs?

    "[True. Or apps could stop going unresponsive. -Raymond]"

    This is kind of like Windows 3 blaming an application for bringing down the OS.

    [The hotkey design dates back to 16-bit Windows. -Raymond]
  36. Danny says:

    3 seconds delay for each non-responsive app? hardly that is the true..maybe in the Windows lab where Ray is sitting, but in the real world try forever. I start a debug session then hit WIN+E to launch another Explorer window, don't respond. Hit few more times, nothing. Double click the Total Commander icon on desktop, nothing. Press CTRL+SHIFT+ESC, nothing. All this indicate the Explorer itself is not responding to it's own internals. Go to IDE, stop debugging session and suddenly on my desktop 6 exporer windows, one Task Manager and a Total Commander windows pop all at the same time. What do you respond to this Ray? It's happening all the time when I debug. Curious, if I just hit Right Click on exporer icon and launch it with "Run as" under different credentials it will pop-up just nicely. So, huh, I guess there is more to it then just this simple explanation of Explorer going on "asking spree" as you imply. I want the entire story, not just the 1st chapter, hope you'll do it as a series.

    [Windows+E and Ctrl+Shift+Esc are not hotkeys for shortcuts. And double-clicking an icon doesn't even involve a hotkey! The scenarios you describe here are unrelated to today's topic. -Raymond]
  37. James says:

    >>I'm sure it's too late to change now, but why didn't explorer originally store the hotkey information internally?

    >[Because RegisterHotKey is a window manager feature, not an Explorer feature. -Raymond]

    But launching shortcuts in response to hotkeys *is* an Explorer feature, so Explorer already must have some kind of internal mapping to know which shortcut to launch for which hotkey.

    I think I can rationalize the behavior as: Explorer can (and probably does) store that information, but that doesn't help in the case described here, where Explorer wants to activate an existing window if possible.  Explorer doesn't necessarily know which window came from which shortcut (if it even was started via a shortcut).  It could try comparing the process name to the shortcut's command-line, or it could keep track of the process handle from CreateProcess and see if that corresponds to the window, but neither of those would work in a case where the window was created by a child process or where a single application instance creates multiple top-level windows.

  38. Marcel says:

    @Danny: Usually that happens if the debugged program currently holds the loader lock for whatever reason.

  39. Lasse Hansen says:

    Finally an explanation! This has been bugging me for years!

    In Windows 7 it has become so prevalent for me that I've switched to AutoHotkey to handle program launch. Now I know this switch won't be temporary.

  40. Jon says:

    If I write a program that uses a small launcher executable to trigger the real program, I can make it so the real program responds to the hotkey message in the same way the launcher does. That lets the program work properly with hotkeys even though the hotkey is configured on a shortcut to the launcher. If explorer used a lookup table to know what process to look for instead of using the message, then it would just end up running the launcher even though the real program is already running.

  41. David Walker says:

    Like some others, I don't understand why Windows is asking the running applications "is this your hotkey"?.  Windows already knows what application to start for a given hotkey (consider the case where there are (effectively) no appliations running.  Windows knows what application it needs to start for a hotkey, and it should be able to tell if that application is running or not.  

    Maybe it can't tell if a running application is the same as the name of the executable that it would start for hotkey X, but that also sounds hard to believe.

    I also agree that if I press a hotkey while the application is already running, I very likely want another copy of that program to start.  This behaviour should be custonizable.

  42. Alex Cohn says:

    This is why I often prefer to remove the DDE enchantment  from HKCR open key.

  43. Jon says:

    "[The hotkey design dates back to 16-bit Windows. -Raymond]"

    Understood, but could that design be improved? Is this a case of "could fix, but other things take priority", or "can't fix due to backwards compatibility constraints"?

    [The benefit probably does not outweigh the costs of implementation, risk of regression, and compatibility risk. See: Minus 100 points. -Raymond]
  44. xp.client says:

    Imagine my horror when the shortcut hotkey feature didn't work on Windows 8 Developer Preview unless you did the RPEnabled trick. Thankfully, it works again in Consumer Preview. But as noted above by many, there is a noticeable delay sometimes compared to XP. And you can't set it for Metro-style app shortcuts.

  45. dsmtoday says:

    It happens quite often that the volume control key presses on my Microsoft keyboard are delayed by approximately 3-6 seconds, especially if I'm in the middle of debugging an application.  Perhaps the Intellitype software is mistakenly passing these keypresses around to all the applications before it changes the volume?  Very frustrating if I need to turn something down quickly.

  46. Neil (SM) says:

    I really like Raymond's personification of explorer here.  Explorer sounds a bit passive-agressive!

  47. @heinke37 says:

    You could open the programs one at a time until the delay started happening.

  48. 640k says:

    [The benefit probably does not outweigh the costs of implementation, risk of regression, and compatibility risk. See: Minus 100 points. -Raymond]

    Why is there sometimes a long delay between pressing a hotkey for a shortcut and opening the shortcut?

    –>

    Because MS cannot afford to code a better OS. Ever.

  49. Annoyed says:

    Like the tv news guy said, "keep f—– that chicken, 640k".

  50. Abel says:

    Wow, thank you so much. You just answered a question I've had for almost a decade (is that even possible?).

Comments are closed.

Skip to main content