2009-10-26 3 views
13

Моя программа помещает значок в системный лоток, потому что пользователь может свести к минимуму его. Однако, если приложение сработает, или я прекратил запуск приложения в VS, он оставляет значок в нем, пока я не надвигаюсь над ним с помощью мыши. Иногда я буду смотреть вниз, и будет около 10 значков.Как предотвратить оставление значка в системном лотке при выходе?

Я могу убедиться, что значок исчезнет?

ответ

21

Там нет никакого способа сделать это. Windows не опросит вашу программу, чтобы убедиться, что она еще жива. Таким образом, ваш значок останется в системном трее, пока вы не скажете ему оставить (обычный выход), или пользователь сделает что-то, что инициирует вызов вашей программы (например, наведение мыши). Только тогда оболочка знает, что ваша программа умерла, и ей нужно очистить значок.

+0

Итак, нет никакого события, которое я могу захватить, если программа умрет? – Malfist

+0

Нет, событий нет. Это «нормальное» поведение ... каждое приложение, имеющее значок в системном трее, оставляет свой значок позади, когда он выходит аномально. – jrista

+1

Очень маловероятно, что у вас не будет возможности очистить значок. AppDomain.ProcessExit - довольно хорошее событие для прослушивания выхода процесса. Если вы не вызовете Environment.FailFast(), это, вероятно, будет вызвано даже в «катастрофических» обстоятельствах. –

3

Перед тем, как выйти, установите для свойства NotifyIcon Visible значение false.

+1

Но он очищает его, когда программа выходит из строя. Но если программа умирает, она убита или падает, она оставляет значок. – Malfist

+2

Судя по количеству продуктов, которые имеют такое же поведение, это трудная проблема. –

+0

хотя это не лучшее решение, но его хороший трюк, чтобы решить его быстро! – Arash

3

Вам необходимо вызвать Dispose на NotifyIcon, чтобы он покинул лоток.

EDIT: есть событие, в которое вы можете подключиться к программе Programs.cs. Для всех приложений Windows, вы будете иметь что-то вроде этого:

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

Класс Application имеет несколько событий, вы можете воспользоваться, чтобы знать, когда ваше приложение умирает:

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

Но где/когда? – Malfist

+1

OP упоминает, что видит проблему только тогда, когда его применение умирает, или он убивает его. В таких ситуациях Dispose() не будет вызываться. –

4

У вас есть несколько вариантов:

1) Написать корневой структурированный обработчик исключений, который обеспечивает уничтожение значка перед выходом. Это требует некоторых усилий, но вы можете в основном добавить свой собственный обработчик исключенных обработчиков в Windows, который будет вызываться в случае многих форм «бум», который затем позволит вам воспользоваться возможностью последней очистки.

2) Напишите приложение монитора, которое спит на вашем основном процессе, обрабатывает и убивает значок, когда он просыпается (основное приложение умерло). Чтобы этот последний сценарий работал хорошо, вы, скорее всего, захотите, чтобы основной процесс НЕ убивал сам значок - или вы могли бы создать способ сообщить приложению монитора, что он должен выйти без разрушения значка (иметь сон приложения монитора как на дескрипторе процесса, так и на именованном событии - и если его разбудил событие, он просто умирает без очистки после основного приложения).

+0

D'oh - Я должен был отметить этот язык. Вариант №1 доступен для C или C++, но я не уверен, что доступен для приложения C#, поэтому вы можете быть вынуждены делать # 2. – Mordachai

+0

# 2 - более надежный вариант, во всяком случае. # 1 было бы неплохо, если бы этот процесс был убит в диспетчере задач или как упоминалось в OP, если бы кто-то внезапно завершил сеанс отладки. –

-1

Мы можем скрыть лотокIcon перед закрытием формы. Add FormClosing Event

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