2009-10-26 11 views
13

Mon programme met une icône dans la barre d'état système car l'utilisateur peut y réduire. Toutefois, si l'application se bloque ou si j'arrête l'exécution de l'application dans VS, elle laisse l'icône jusqu'à ce que je la survole avec la souris. Parfois, je vais regarder là-bas et il y aura une dizaine d'icônes.Comment éviter de laisser une icône dans la barre d'état système à la sortie?

Je peux m'assurer que l'icône disparaît?

Répondre

21

Il n'y a aucun moyen pour faire ça. Windows n'interroge pas votre programme pour voir s'il est toujours vivant. Par conséquent, votre icône restera dans la barre d'état système jusqu'à ce que vous lui disiez de quitter (sortie normale), ou l'utilisateur fait quelque chose qui initie un appel à votre programme (tel que le survol de la souris). Ce n'est qu'alors que le shell sait que votre programme est mort et qu'il doit nettoyer votre icône.

+0

Donc, il n'y a pas d'événement que je peux attraper au cas où le programme meurt? – Malfist

+0

Non, il n'y a pas d'événement. C'est un comportement "normal" ... chaque application qui a une icône de barre d'état système laisse son icône derrière lorsqu'elle se ferme anormalement. – jrista

+1

Il est très peu probable que vous n'ayez pas l'occasion de nettoyer votre icône. AppDomain.ProcessExit est un très bon événement à écouter pour la sortie du processus. Sauf si vous appelez Environment.FailFast() il sera probablement appelé même dans des circonstances 'catastrophiques' –

3

Avant de quitter, définissez la propriété NotifyIcon Visible sur false.

+1

Mais il l'efface lorsque le programme se termine correctement. Mais si le programme meurt, est tué, ou plante, il laisse l'icône. – Malfist

+2

A en juger par le nombre de produits qui ont ce même comportement, c'est un problème difficile à résoudre. –

+0

bien que ce ne soit pas la meilleure solution mais son bon truc pour le résoudre rapidement! – Arash

3

Vous devez appeler Dispose sur le NotifyIcon pour qu'il quitte le bac.

EDIT: Il existe un événement auquel vous pouvez vous connecter dans votre fichier Program.cs. Pour toutes les applications Windows, vous aurez quelque chose comme ceci:

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

La classe d'application a quelques événements que vous pouvez profiter de savoir quand meurt votre application:

 Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 
     Application.ApplicationExit += new EventHandler(Application_ApplicationExit); 
+0

Mais où/quand? – Malfist

+1

L'OP mentionne qu'il ne voit le problème que lorsque son application meurt ou qu'il le tue. Dans ces situations, Dispose() ne sera pas appelé. –

4

Vous avez plusieurs options:

1) un gestionnaire d'exceptions structuré racine qui assure la destruction de l'icône avant la sortie. Celui-ci prend un peu d'effort - mais vous pouvez simplement ajouter votre propre gestionnaire d'exception non géré à Windows qui sera appelé dans le cas de plusieurs formes de "boom" qui vous permettra alors une occasion de nettoyage dernier recours. 2) Écris une application de surveillance qui dort sur la poignée de vos processus principaux, et tue l'icône quand elle se réveille (l'application principale est morte). Pour que ce dernier scénario fonctionne bien, vous souhaiterez probablement que le processus principal ne tue PAS l'icône elle-même - ou vous pouvez créer un moyen d'indiquer à l'application moniteur qu'il doit quitter sans détruire l'icône à la fois sur le handle de processus et sur un événement nommé - et s'il est réveillé par l'événement, il meurt simplement sans nettoyage après l'application principale).

+0

D'oh - J'aurais dû noter la langue. L'option n ° 1 est disponible pour C ou C++, mais je ne suis pas sûr que cela soit disponible pour une application C# - vous serez donc forcés de faire # 2. – Mordachai

+0

# 2 est l'option la plus robuste, de toute façon. # 1 serait pas bon si le processus a été tué dans le Gestionnaire des tâches, ou comme l'OP mentionné, si l'on devait mettre fin abruptement à une session de débogage. –

-1

Nous pouvons cacher trayIcon avant la fermeture du formulaire. Ajouter un événement de clôture de formulaire

NotifyIcon ni; 
... 
... 
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    ni.Visible = false; 
}