views:

698

answers:

3

Hi there,

I've got a .Net 3.5 C# Winforms app. It's got no GUI as such, just a NotifyIcon with a ContextMenu.

I've tried to set the NotifyIcon to visible=false and dispose of it in the Application_Exit event, as follows:

        if (notifyIcon != null)
        {
            notifyIcon.Visible = false;
            notifyIcon.Dispose();
        }

The app gets to the code inside the brackets, but throws a null ref exception when it tries to set Visible = false.

I've read in a few places to put it in the form closing event, but that code never gets hit (maybe as I don't have a form showing as such?).

Where can I put this code so it actually works? If I don't put it in, I get the annoying lingering icon in the tray until you move the mouse over it.

Cheers.

EDIT

Just something extra I've noticed...........

I'm using ClickOnce in the app.........if I just exit the app via the ContextMenu on the NotifyIcon, no exception is logged.

Just when the Application_Exit event is fired after the applicaiton has checked for an upgrade here..

private void CheckForUpdate()
{
    EventLogger.Instance.LogEvent("Checking for Update");
    if (ApplicationDeployment.IsNetworkDeployed && ApplicationDeployment.CurrentDeployment.CheckForUpdate())
    {
        EventLogger.Instance.LogEvent("Update available - updating");
        ApplicationDeployment.CurrentDeployment.Update();
        Application.Restart();
    }
}

Does this help?

+3  A: 

This code works for me, but I don't know how you are keeping your application alive, so... without further ado:

using System;
using System.Drawing;
using System.Windows.Forms;

static class Program
{
    static System.Threading.Timer test = 
        new System.Threading.Timer(Ticked, null, 5000, 0);

    [STAThread]
    static void Main(string[] args)
    {
        NotifyIcon ni = new NotifyIcon();
        ni.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
        ni.Visible = true;

        Application.Run();
        ni.Visible = false;
    }

    static void Ticked(object o) {
        Application.Exit();
    }
}
Matthew Scharley
A: 

Sometimes Application_Exit event can be raised several times Just put notifyIcon = null; in the end

if (notifyIcon != null)
{
    notifyIcon.Visible = false;
    notifyIcon.Dispose();
    notifyIcon = null;
}
Bogdan_Ch
Actually, now that I think about it, I'd recommend against using this event for this because it's possible to have several Application.Run() loops going on different threads and they will all trigger an Exit event which might cause your icon to disappear prematurely.
Matthew Scharley
Totally agree with you! I prefer not to use this event in my applications for any clean-up purposes. However, it is the most simple answer to the question "why this code throws an exception". As to my ideas how to design this code in another way, I could propose to create a wrapper disposable class around notifyIcon, so it will control the lifetime of the notifyIcon. and then write using (new NotifyIconController()) { Application.Run() }; or something like this
Bogdan_Ch
A: 

This is what I'm doing in WPF.

I am using this in conjunction to David Anson's Minimize to tray sample app, which lets you hook up a tray icon to a window (you may have multiple windows open).

Just added this code to the constructor for MinimizeToTrayInstance.

_window.Closed += (s, e) => 
{
        if (_notifyIcon != null)
        {
            _notifyIcon.Visible = false;
            _notifyIcon.Dispose();
            _notifyIcon = null;
        }
};
Simon_Weaver