3

Edit: I rephrased my question, please ignore all of the comments below (up to the 7th of May).

First off, I'll try to explain the problem:
My process is trying to show a Deskband programmatically using ITrayDeskBand::ShowDeskBand.
It works great at any time except for when the OS is loading all of its processes (after reset or logout).

After Windows boots and starts loading the various applications\services, the mouse cursor is set to wait for a couple of seconds (depends on how many applications are running \ how fast everything is).

If the mouse cursor is set to wait and the process is running during that time, the call will fail.
However, if my process waits a few seconds (after that time the cursor becomes regular) and then invokes the call, everything works great.

This behavior was reproduced both on Windows 7 and Windows Vista.

So basically what I'm asking is :

1) Just for basic knowledge, What the OS does when the cursor is set to busy?
2) The more important question : How can i detect programmatically when this process is over?

At first, I thought that explorer hadn't loaded properly so I've used WaitForInputIdle but it wasn't it.

Later I thought that the busy cursor indicates that the CPU is busy so I've created my process using IDLE_PRIORITY_CLASS but idle times were received while the cursor was busy.

Omer
  • 661
  • 7
  • 21
  • Have you try to put your program to the Startup folder? – Ray Cheng Apr 28 '12 at 08:47
  • No, I have an entry @ HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run – Omer Apr 28 '12 at 08:51
  • take a look at this one. http://www.pcreview.co.uk/forums/startup-apps-load-sequence-t2556763.html even if you may not be using windows xp, the sequence may have been the same. – Ray Cheng Apr 28 '12 at 08:57
  • Thanks Ray but even if my program loads up last in the sequence I still may receive a race condition (if the other program loads for a lot of time). – Omer Apr 28 '12 at 09:14
  • since you don't know how long they'll run, so the only option is to wait for them to finish first. in your program, monitor the list of processes and if they are no longer on the list, then continue your program, otherwise, keep waiting. if you need code samples, take a look at http://stackoverflow.com/questions/599663/retrieve-a-complete-processes-list-using-c-sharp – Ray Cheng Apr 28 '12 at 09:23
  • I just discovered WaitForInputIdle function, which basically waits for the process to initiate - I hope that will help. – Omer Apr 28 '12 at 09:36
  • 3
    How do you define "after the computer has finished booting"? If you define it as "after all other programs have finished loading", what would happen if two such programs did that? Would they wait for each other indefinitely? Not everything can be last. – jamesdlin Apr 28 '12 at 11:15
  • 2
    By definition, it's 'finished booting' if your program is running. All of that running programs and logging in happens after the OS has booted. – dave Apr 28 '12 at 22:39
  • 3
    What you need is to more precisely decide what it is you're waiting for -- sounds like it's only 'after program X', not 'after all possible programs'. Can't you simply write code that waits until 'program X' has done whatever it does? What is the nature of the race condition? – dave Apr 28 '12 at 22:41
  • For that matter, I'm trying to call a shell function (ITrayBand::ShowDeskBand) while the OS is loading all of the applications. If the OS is busy loading the application (Can see it by the cursor changing) the call will fail, however when the CPU is idle it will work. – Omer Apr 30 '12 at 13:19
  • 1
    You'd better hope the user doesn't have another application that also waits for all others to finish loading before starting, otherwise neither of you will ever start! – Jonathan Potter May 01 '12 at 11:54

3 Answers3

5

Windows never stops loading applications and/or services!

As a matter of fact, applications come and go, some of these interactively some of these without any user interaction. Even Services are loaded at different points of time (depending on their settings and the external conditions - e.g the Smard Card Resource Manager Service might start only when the OS detects that a Smard Card device has connected). Applications can (but must not) stop automatically so do some Services.

One never knows when Windows has stop to load ALL applications and/or Services.

mox
  • 6,084
  • 2
  • 23
  • 35
  • Thanks, but it's not something I didn't know. The OS sets the cursor to busy after the computer boots up from some reason, probably it's indicating that the programs\services are loading. Basically what I'm trying to figure out is: given a list of all the processes\services that start up after I'm booting, how do I know when all of them are finished loading? – Omer May 08 '12 at 12:17
  • 1
    Ok. Even for Services that are configured to be managed during startup, this depends on the configurations of the services (e.g delay-start, retry count when a failure occurs, etc...) One can never know if/when all services (configured at boot up) are ALL completely done (complete). – mox May 08 '12 at 12:27
  • 1
    He's simply approaching this the wrong way. He should be testing for the busy state, and just waiting until it has passed to continue processing. Checking for the status of every process is silly. – Nathan Rice May 08 '12 at 15:32
5

If ITrayDeskBand::ShowDeskBand fails, then wait for the TaskbarCreated message and then try again. (This is the same technique used by notification icons.)

Raymond Chen
  • 44,448
  • 11
  • 96
  • 135
  • it sounds like exactly what I need, I'll try it. However sometimes my process will execute after the taskbar had been created, how can I tell if its created? – Omer May 09 '12 at 09:56
  • Then the call to `ITrayDeskBand::ShowDeskBand` will succeed. – Raymond Chen May 09 '12 at 14:08
1

The obvious approach would be to check whether ShowDeskband worked or not, and if not, retry it after a few seconds. I'm assuming you've already considered and rejected this option.

Since you seem to have narrowed down the criteria to which cursor is being displayed, how about waiting for the particular cursor you are wanting? You can find which cursor is being shown like this:

CURSORINFO cinfo;
ICONINFOEX info;

cinfo.cbSize = sizeof(cinfo);
if (!GetCursorInfo(&cinfo)) fail();

info.cbSize = sizeof(info);
if (!GetIconInfoEx(cinfo.hCursor, &info)) fail();

printf("szModName = %ws\n", info.szModName);
printf("wResID = %u\n", info.wResID);

Most of the simple cursors are in module USER32. The relevant resource IDs are listed in the article on GetIconInfo.

You apparently want to wait for the standard arrow cursor to appear. This is in module USER32, and the resource ID is 32512 (IDC_ARROW).

I suggest that you check the cursor type ten times a second. When you see the arrow cursor ten times in a row (i.e., for a full second) it is likely that Explorer has finished starting up.

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • I'm not going to delete this answer, because I think it's interesting that you can do this, but Raymond's answer is better. – Harry Johnston May 09 '12 at 02:30
  • Determining program state from the UI has always been a bad idea. What if something else changes the cursor? Or if someone has a custom "busy" cursor set? – Deanna May 14 '12 at 10:19
  • @Deanna: absolutely true, but there may be times when there is no other option (although as it turns out this isn't one of them). – Harry Johnston May 14 '12 at 21:18