90

There are many questions on SO asking same doubt. Solution for this is to set

notifyIcon.icon = null and calling Dispose for it in FormClosing event.

In my application, there is no such form but has Notification icon which updates on Events. On creation, I hide my form and make ShowInTaskbar property false. Hence I can not have a "FormClosing" or "FormClosed" events.

If this application gets event to exit, It calls Process.GetCurrentProcess().Kill(); to exit.

I have added notifyIcon.icon = null as well as Dispose before killing, but still icon remains taskbar until I hover mouse over it.

EDIT: If I assume that this behaviour is due to calling GetCurrentProcess().Kill(), Is there any elegant way to exit from application which will clear all resources and remove icon from system tray.

Swanand
  • 4,027
  • 10
  • 41
  • 69
  • 2
    Time to accept an answer don't you think :D Let me suggest you the one of "The Muffin Man" :D – Felix D. Jul 14 '16 at 09:47
  • @Nudity Problem is I just got rid of that notify icon... And now I don't have that code to verify any solution :-) – Swanand Jul 14 '16 at 14:20
  • Will I just did :D and the Dispose() fixed it :D – Felix D. Jul 14 '16 at 15:07
  • One option is to refresh the traybar after killing the process, see the posts at https://stackoverflow.com/questions/2311877/tray-icon-does-not-disappear-on-killing-process and https://stackoverflow.com/questions/55703983/update-redraw-system-tray-window-after-a-button-is-removed for details – yoel halb May 19 '22 at 18:35

15 Answers15

55

You can either set

notifyIcon1.Visible = false;

OR

notifyIcon.Icon = null;

in the form closing event.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Jason Dias
  • 769
  • 1
  • 7
  • 9
22

The only solution that worked for me was to use the Closed event and hide and dispose of the icon.

icon.BalloonTipClosed += (sender, e) => { 
                                            var thisIcon = (NotifyIcon)sender;
                                            thisIcon.Visible = false;
                                            thisIcon.Dispose(); 
                                        };
The Muffin Man
  • 19,585
  • 30
  • 119
  • 191
  • 5
    This should be the accepted answer ... `Dispose()` is what you need there ! – Felix D. Jul 14 '16 at 09:45
  • what is this called? += (sender, e) => { // code }; – The Muffin Boy Sep 16 '16 at 19:01
  • 2
    @user3365695 It's a lambda expression. Check this link out with examples of the 3 ways to specify the delegate https://msdn.microsoft.com/en-us/library/bb882516.aspx?f=255&MSPPError=-2147217396 – The Muffin Man Sep 17 '16 at 18:13
  • I remember when I was learning delegates were not explained well. A delegate is simply a way to provide the name of a method to be invoked later by something. You can use any method you've made that matches the signature the event expects. In this case we register a method to be called once the Balloon tip internally invokes the `BalloonTipClosed` event. In this example, syntactically we don't provide the name of a method, we define what's called an anonymous function/method. This is a newer code feature which is why you see multiple ways to do it notably `delegate(string s) {//code}`. – The Muffin Man Jul 25 '18 at 17:49
  • Application.Exit(); NotifyIcon = null; works every time on multiple "windows reinstalls" - seperate issue lol – WiiLF Dec 20 '21 at 23:15
18

Components just must be disposed in the right order like this :

NotifyIcon.Icon.Dispose();

NotifyIcon.Dispose();

Add this to the MainWindow closing event.

Hope this will help.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Shim-Sao
  • 2,026
  • 2
  • 18
  • 23
  • 1
    i think that perhaps it's important to note that stopping debugging doesn't trigger override void OnExit(ExitEventArgs e), disposing will not be triggerd – Walter Verhoeven Jan 23 '22 at 07:15
12

Use this code when you want to do it when you press the Exit or Close button:

private void ExitButton_Click(object sender, EventArgs e)
{
    notifyIcon.Dispose();
    Application.Exit(); // or this.Close();
}

Use this code when you want to do it when the form is closing:

private void Form1_FormClosing(object sender, EventArgs e)
{
    notifyIcon.Dispose();
    Application.Exit(); // or this.Close();
}

The important code is this:

notifyIcon.Dispose();
tanascius
  • 53,078
  • 22
  • 114
  • 136
Pouya
  • 182
  • 1
  • 6
  • 1
    I tried the following code and it worked. private void Window_Closed(object sender, EventArgs e) { mNotifyIcon.Dispose(); } – Garland Mar 01 '18 at 23:55
11

Use notifyIcon.Visible = False in FormClosing event

demonplus
  • 5,613
  • 12
  • 49
  • 68
Ismael
  • 369
  • 3
  • 7
  • 2
    To do a _clean_ cleanup you still should call `notifyIcon.Dispose()`. When your class doesn't have a function wehre you could call this, you should implement `IDisposable`. – Daniel Eisenreich Sep 20 '18 at 09:46
  • Not sure why this is not marked as the answer but it fixed my issue as well...thanks @Ismael – Kevin Moore Apr 26 '19 at 19:53
  • @KevinMoore because the OP explicitly stated that he has no `Form` on which they could handle the `FormClosing` event – ardila Apr 19 '20 at 07:50
4

The only way that works to me was:

  1. On design screen changing notifyicon1 property visible=false

  2. Insert the code below on main form "activated" event:

NotifyIcon1.Visible = True
  1. Insert the code below on main form "closing" event:
NotifyIcon1.Visible = false
NotifyIcon1.Icon.Dispose()
NotifyIcon1.Dispose()
Rafael
  • 41
  • 1
3

This is normal behaviour, unfortunately; it's due to the way Windows works. You can'r really do anything about it.

See Issue with NotifyIcon not dissappearing on Winforms App for some suggestions, but none of them ever worked for me.

Also see Notify Icon stays in System Tray on Application Close

Microsoft have marked this as "won't fix" on Microsoft Connect.

Community
  • 1
  • 1
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • 3
    i feel like windows has been doing this forever. – j_mcnally Feb 06 '13 at 07:39
  • OSX will often leave a GAP in the task bar in similar situation, just a quirk i guess of how both OSes draw their task / menu bars. – j_mcnally Feb 06 '13 at 07:39
  • Isn't there any elegant way to Exit from this process instead of "GetCurrentProcess.Kill()" and Will that change my this behaviour? – Swanand Feb 06 '13 at 07:42
  • It could! I feel like the fact you are killing it, is what is causing some of the issue. You could try waiting for the next run loop before killing, after your set the icon nil and disposing. – j_mcnally Feb 06 '13 at 07:46
  • 1
    @MatthewWatson Can you provide me any link where it says "Won't fix"? – Swanand Feb 08 '13 at 07:16
  • I guess there must be some fix for this - utorrent for example has also icon in system tray. But, when it exits, the icon disapears. – FrenkyB Nov 17 '13 at 16:39
  • This is normal behavior, but you can get around it. See answers about NotifyIcon.Visible – scone Jun 01 '15 at 01:39
2

I don't think WPF has it's own NotifyIcon, does it? If you're using the 3rd party Harcodet.Wpf.TaskbarNotification, then try this:

In order to prevent my app from closing when the window is closed (run in background), I separated the logic for closing the window (hitting the x button in the upper right) and actually shutting it down (through the context menu). To make this work, make your context menu set _isExplicitClose to true. Otherwise, it'll just hide the window and continue to run.

What this does is, on explicit close, hide tray icon and the form before closing. This way the icon isn't hanging around after the application is shutdown.

private bool _isExplicitClose;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
    base.OnClosing(e);

    if (!_isExplicitClose)
    {
        e.Cancel = true;
        Hide();
    }
}

protected void QuitService(object sender, RoutedEventArgs e)
{
   _isExplicitClose = true;
   TaskbarIcon.Visibility = Visibility.Hidden;
   Close();
}
Sinaesthetic
  • 11,426
  • 28
  • 107
  • 176
2

Try Application.DoEvents(); after setting notifyIcon.Icon to null and disposing:

notifyIcon.Icon = null;
notifyIcon.Dispose();
Application.DoEvents();

And consider Environment.Exit(0); instead of Process.GetCurrentProcess().Kill().

Cubi73
  • 1,891
  • 3
  • 31
  • 52
1

i can tell you can solve the problem simply using the .dispose() method, but that is not called if you kill the process instead of exit the application.

please refer to Application.Exit if you have built a simple Windows Form application else refer to Environment.Exit that is more general.

Lanello
  • 59
  • 3
1

I tried all of these and none of them worked for me. After thinking about it for a while I realized that the application creating the "balloon" was exiting before it had a chance to actually dispose of the balloon. I added a while loop just before Application.Exit() containing an Application.DoEvents() command. This allowed my NotifyIcon1_BalloonTipClosed to actually finish disposing of the icon before exiting.

while (notifyIcon1.Visible)
{
    Application.DoEvents();
}
Application.Exit();

And the tip closed method: (You need to include the thisIcon.visible = false in order for this to work)

private void NotifyIcon1_BalloonTipClosed(object sender, EventArgs e)
{
    var thisIcon = (NotifyIcon)sender;
    thisIcon.Icon = null;
    thisIcon.Visible = false;
    thisIcon.Dispose();
}
kiner_shah
  • 3,939
  • 7
  • 23
  • 37
0

I had the exact same problem as you.

The proper way are send WM_CLOSE message to a process.
I use the c# code I found in this article.
http://social.msdn.microsoft.com/Forums/vstudio/en-US/82992842-80eb-43c8-a9e6-0a6a1d19b00f/terminating-a-process-in-a-friendly-way

vic
  • 440
  • 1
  • 4
  • 10
0

edit codes of ...Designer.cs as below coding.

        protected override void Dispose(bool disposing)
           {
           if (disposing )
               {
               this.notifyicon.Dispose();
               }
           base.Dispose(disposing);
           }
Can DOGRU
  • 69
  • 1
  • 5
0

I couldn't make any one of the other solutions work. It turned out to be kind of a hybrid of all the above! I hunted and pecked until I had a consistently working solution both in debug and in EXE execution modes! I have no idea why MSFT would mark this as "Not going to fix"? I wish I had that liberty!

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
        //THIS CODE IS CRAZY BUT MUST BE DONE IN ORDER TO PROPERLY REMOVE THE SYSTEM TRAY ICON!
        //GREAT ARTICLE ON THIS ON STACK OVERFLOW
        //https://stackoverflow.com/questions/14723843/notifyicon-remains-in-tray-even-after-application-closing-but-disappears-on-mous

        //BTW THIS IS KIND OF A BLEND OF ALL THE SOLUTIONS BECAUSE I COULD NOT FIND A SINGLE SOLUTION THAT WOULD WORK!
        systray_icon.Visible = false;
        while (systray_icon.Visible)
        {
            Application.DoEvents();
        }
        systray_icon.Icon.Dispose();
        systray_icon.Dispose();
        Environment.Exit(1);
    }
cigien
  • 57,834
  • 11
  • 73
  • 112
BitWiseByteDumb
  • 159
  • 1
  • 12
-2

The right answer has already been given. But you must also provide a delay, for example with a timer. Only then the application can still remove the icon in the background.

private System.Windows.Forms.Timer mCloseAppTimer;
private void ExitButton_Click(object sender, EventArgs e) 
{ 
    notifyIcon.Visible = false; notifyIcon.Dispose; 
    mCloseAppTimer = new System.Windows.Forms.Timer(); 
    mCloseAppTimer.Interval = 100; 
    mCloseAppTimer.Tick += new EventHandler(OnCloseAppTimerTick); 
} 
private void OnCloseAppTimerTick(object sender, EventArgs e) 
{ 
    Environment.Exit(0); // other exit codes are also possible 
}
Simon H
  • 2,495
  • 4
  • 30
  • 38
  • 1
    Surely the use of a timer is an overkill - wouldn't Thread.Sleep(1000), do the same thing? You could even use it within a new thread so it doesn't 'pause' any GUI ect – Mark Jun 22 '18 at 10:16