How can I wait until all startup applications have finished launching?


A customer wanted to know how to detect that all startup applications have finished launching. They wanted to wait until everything settled down before proceeding with some task.

What if two programs did this?

Suppose two programs both wanted to detect that all startup applications have finished launching. Each one would sit there waiting for the other, because this is one of those I want to be the last to do something, even laster than the other guy who wants to do something last things.

If you want to wait until the system is idle to perform some task, you can use the Task Scheduler to create an idle-time task. This has the benefit of coordinating multiple idle-time tasks so that you don't have the phenomenon of two applications both trying to do things when they think nobody else is doing anything, resulting in an Alphonse-and-Gaston state: The system goes idle, and both Alphonse and Gaston start doing their idle-time tasks. But Alphonse notices that Gaston is busy and backs off; at the same time, Gaston notices that Alphonse is busy and backs off. Now the system is idle again, and both Alphonse and Gaston start their idle-time tasks, and the cycle continues. The computer gets into this weird state where it keeps waking up, going to sleep, waking up, going to sleep, and never actually making progress.

Comments (27)
  1. Joshua says:

    Well that assumes utter idiocicy to get into the problem state. Set thy priority and thy IO priority to very low then try to work.

    [They want their task to run at high priority, but after the startup apps are finished launching. Setting their task to low priority would not accomplish that, because it would then be interrupted by non-startup tasks. -Raymond]
  2. Count Zero says:

    I understand why it isn't possible, but...

    :heavy breathing:

    ...you have to admit it would be nice.

  3. acq says:

    Thanks for "Alphonse and Gaston" tip, one good full comic:

    1.bp.blogspot.com/.../Alphonse+and+gaston2.jpg

  4. Cesar says:

    The problems start with the first sentence. "Finished launching". What's the definition of "finished launching"? The kernel started the initial thread? The process entered wWinMain? The process created at least one window or notification icon? The process is waiting for the next event with an empty event queue? What if the process has more than one thread with an event loop? And so on.

    As for "what if two programs did this", I have an easy solution. Suppose hypothetically that we have two functions, IFinishedLaunching() and WaitForEveryoneToFinishLaunching(). Simply make WaitForEveryoneToFinishLaunching() imply IFinishedLaunching() as its first action (before waiting). Then there will be no risk of deadlock, the barrier will release once everyone has called either of these functions. Replace IFinishedLaunching() by whatever implicit action you want (idle in the event loop, created a window, etc) and you have a usable WaitForEveryoneToFinishLaunching() function.

  5. DWalker says:

    "Even laster"?  I like that!  I want to be lastest!

  6. DWalker says:

    ... and there are various "startup delayer" programs around.  Some of them have an option to wait until the system is "idle enough" (this is configurable) after system boot, and then they can launch one or more programs.  This is very similar to what Raymond suggests with an idle-time scheduled task.

  7. DWalker says:

    Finally....  once you have detected that all startup tasks have finished, if the user "wanted to wait until everything settled down before proceeding with some task", they very likely fire off their task and they are done with it.  

    When you say "What if two programs did this" and "But Alphonse notices that Gaston is busy and backs off", that's likely beyond the scope of the original problem.  The original problem was how to wait and then fire off a task.  How to create a task that runs at "high priority yet backs off if the system is not idle" is a conceptual mind warp anyway.  :-)

  8. Yuri says:

    Typical viewpoint of a manager, complete failure to grasp the concept of multitasking.

  9. Nico says:

    Reminds me of a question on Stack Exchange a while back: superuser.com/.../729738

    At the time I didn't consider an on-idle task.  That's got me curious though how well it works for system startup (which will depend on the definition of "idle" I guess).  However, at first glance (msdn.microsoft.com/.../aa383561%28v=vs.85%29.aspx) it appears that the check is only made every 15 minutes on Windows 7.  Might not work the best for that scenario.

  10. Evan says:

    @Yuri: Typical viewpoint of a manager, complete failure to grasp the concept of multitasking.

    Except multitasking is a leaky abstraction. Competition for resources between two processes will slow both down, and in the case of I/O in particular I'm nearly positive it is even very possible that Time(X and Y simultaneously) can be rather higher than Time(X alone) + Time(Y alone).

    As a result of that fact, there are a number of reasons why one could quite reasonably either not want to slow down the startup tasks or not want the startup tasks to slow down your task.

  11. I have an application that (kind of) needs to do this: the scripting engine that installs software for me in our teaching labs.  (Basically a homegrown version of the Microsoft Deployment Toolkit, originally developed before MDT existed.)

    It turned out that if the scripting engine launched an installer too soon after logon, the UI automation would sometimes behave erratically, because too many startup applications were stealing focus unexpectedly, and sometimes this would happen at just the wrong time.  So I needed it to wait until things settled down a bit before getting started.  (If you've got two scripting engines running on the same machine at the same time, whether they start up properly is the least of your problems, so that at least wasn't an issue.)

    I didn't spend a lot of time thinking about it, as I recall.  Launching the application via the startup menu got me most of the way there, because they don't get launched until Explorer is well and truly ready to do so, and then I just stuck in a 30-second wait.  In the grand scheme of things, an extra 30 seconds per reboot is negligible.  But then, I'm the only person who uses this software, so I can afford to take a pragmatic approach to coding it. :-)

  12. cheong00 says:

    It's like asking "how can I change the program so it'll reserve at least 50% of overall CPU time for other process?"

  13. Mike S says:

    I've been in this situation, where starting up everything at once would hammer the database, making the DBAs scream. So we had a launcher which would launch a couple of apps, wait for them to signal that their initial load to finish, and then launch a few more. It worked pretty well.

  14. Ken Hagan says:

    Funnily enough, ethernet (on a shared medium, not a star topology) does exactly this. Everyone who has data to transmit waits for the line to go quiet. The trick is that everyone then waits for a random period before trying and monitors the state of the line whilst they are doing so.

    I imagine something similar would work for this customer. They aren't certain to be the lastest last, but they'd be last enough.

  15. Ken Hagan says:

    To clarify my previous reply. They'd be laster than anyone else who wasn't using the same algorithm, which means they'd do their work after all those tasks that couldn't wait.

    Obviously if you really want to be last then you need to hook shutdown, not startup.

  16. Yuri says:

    @Evan

    it is even very possible that Time(X and Y simultaneously) can be rather higher than Time(X alone) + Time(Y alone)

    This is pretty much the point that multitasking doesn't allow. You cannot enforce Time(X alone) + Time(Y alone) in the Windows multitasking environment. The solution of launching an idle-time task solves the 'Run when ressources are available' problem while still allowing to launch other task simultaneously. A hard requirement to do Time(X alone) + Time(Y alone) would require an OS optimized for real-time process.

  17. Danny says:

    Having the background of embedded real-time systems, where the CPU load is not allowed to go bellow 70% (or the management will consider a cheaper CPU in order to make it more economically feasible), this is a non issue for me. Read entries in registry for start-up applications, give them a bit of time to launch, check they finally settled in with their main window(s) and verify the overall CPU load. If lower then 10%, fire my high priority thread and be done with it. And also make it a wait maximum of 5 minutes. Job accomplished, in worse case scenario of 2 applications using same algorithm, one will start 5 minutes later, still doing real work.

  18. Marc K says:

    DWalker says it best with "idle enough".  The customer was probably wanting to know how to delay until the system has quieted down so that his task doesn't make an already busy system slower.  We've all had that frustration of logging in to a system being tricked by a desktop that looked ready, but was totally unresponsive to input.  I think the customer's question is being interpreted too literally and the "us the Task Scheduler" suggestion was probably exactly what they needed.

  19. Marc K says:

    @Harry Johnston: "...at just the wrong time."

    This would lead me to conclude that you've got some sort of race condition going on.  By waiting, you reduce the likelihood of it occurring, but do not fix the underlying problem.

  20. Hans says:

    I wish windows update could be set to high priority when system is idle.

    Installing updates takes an hour but cpu is stuck at 50 percent.

    [It's not a priority issue. It's because your machine is dual-core. -Raymond]
  21. Hans says:

    OK, I was under the impression windows update was programmed explicitly to not hog the cpu so user tasks could run too.

    But if this is not the case as you state, why they are not multithreaded to take use of all cores?

    [You'd have to ask them. My guess is that the code is intended to run when nobody is there, so who cares how many cores it uses? (Besides, you probably don't want to be installing multiple updates in parallel.) -Raymond],/DIv>
  22. @Mark K: yes, exactly.

    The simplest example is when you're generating synthetic keystrokes.  You have to activate the window you want, wait a bit to make sure it's ready, then generate the keystroke.  If another process jumps up and steals focus, the keystroke will go to it instead of the window it was meant for.  I don't think there's any reasonable way to prevent it.

    Even with more sophisticated techniques, my experience suggests that you can still run into trouble, though it isn't as common.  If you're automating a button push, say, the target application might not always behave as expected if another application steals focus at the same time.  

  23. Joker_vD says:

    @Harry Johnson: "I don't think there's any reasonable way to prevent it."

    Well, unless you could send a keystroke to a window without a focus, but how crazy would that be?

  24. Gabe says:

    Joker_vD: It's quite likely that the standard SendKeys method doesn't have a way to send a keystroke to a window without focus.

    But even so if it did, that doesn't solve the problem of not being able to click on a window that isn't on top. How can you automate dismissing a popup window if you can't guarantee that there won't be a window covering it?

  25. @Gabe: yes, the supported methods for synthesizing a keystroke don't allow you to send it to any particular application, it is added to a global queue in the same way as an actual keystroke.

    It should in theory be possible to send the appropriate window messages to a specific application "as if" a keystroke had been received, but in practice I gather this is a lot harder than it sounds.  (Besides, if an application receives a message at a time when it knows that message shouldn't be possible, the results may be unpredictable.)

  26. Joker_vD says:

    @Gabe: Well, again, get the window's handle, and send it WM_LBUTTONDOWN and WM_LBUTTONUP messages.

    @Harry Johnston: Since the application doesn't control its environment, but the environment controls the application (duh), the application really shouldn't make arbitrary assumptions about what environment will do. If it's possible for any thread to send any message to any window, then there is no such thing as a "message that shouldn't be possible at this time".

  27. Beldantazar says:

    @Joken_vD: Because we all know how developers never make stupid assumptions about what can and can't happen.

Comments are closed.

Skip to main content