views:

490

answers:

4

My program puts an icon in the system tray because the user may minimize to it. However, if the application crashes, or I stop the app from running in VS it leaves the icon in it until I hover over it with the mouse. Sometimes I'll look down there and there will be 10 or so icons.

I can I make sure the icon goes away?

+1  A: 

Before you exit, set the NotifyIcon Visible property to false.

driis
But it clears it when the program exits properly. But if the program dies, is killed, or crashes it leaves the icon.
Malfist
Judging from the number of products that have this same behavior, it's a hard problem to solve.
Michael Petrotta
+1  A: 

You need to call Dispose on the NotifyIcon for it to leave the tray.

EDIT: There's an event you can hook into in your Program.cs. For all Windows apps, you'll have something like this:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

The Application class has a few events you can take advantage of to know when your app dies:

        Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
        Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
BFree
But where/when?
Malfist
The OP mentions that he sees the problem only when his application dies, or he kills it. In those situations, Dispose() won't be called.
Michael Petrotta
+10  A: 

There is no way to do this. Windows does not poll your program to see if it's still alive. Therefore, your icon will stay in the system tray until you either tell it to leave (normal exit), or the user does something that initiates a call to your program (such as mouseover). Only then does the shell know that your program has died and it needs to clean up your icon.

JSBangs
So there's no event I can grab in case the program dies?
Malfist
No, there is no event. This is "normal" behavior...every app that has a system tray icon leaves its icon behind when it exits abnormally.
jrista
It's very unlikely that you will not have an opportunity to clean up you icon. AppDomain.ProcessExit is a pretty good event to listen to for process exit. Unless you call Environment.FailFast() it will likely be called even in 'catastrophic' circumstances
Jan Bannister
@Jan: I would hope that if you terminate the process (as through Task Manager), it would die instantly instead of running some cleanup code. I don't know if that's the case or not, but it fits the behavior I've observed. I would also assume that terminating an app through the debugger in VS would similarly kill it without running any additional code.
rmeador
Mordachai
+3  A: 

You have several options:

1) Write a root structured exception handler that ensures the destruction of the icon before exit. This one takes some effort - but you can basically add your own unhandled exception handler to Windows which will be called in the case of many forms of "boom" which will then allow you some last-ditch clean up opportunity.

2) Write a monitor application that sleeps on your main processes handle, and kills the icon when it wakes up (the main application has died). To make this latter scenario work well, you'll likely want the main process to NOT kill the icon itself - or you could create a way to tell the monitor app that it should exit w/o destroying the icon (have the monitor app sleep on both the process handle and a named event - and if woken by the event then it simply dies w/o cleaning up after the main app).

Mordachai
D'oh - I should have noted the language. Option #1 is available for C or C++, but I'm not sure that is available to a C# app - so you may be forced to do #2.
Mordachai
#2 is the more robust option, anyway. #1 would be no good if the process were killed in Task Manager, or as the OP mentioned, if one were to abruptly end a debug session.
P Daddy