Creating a background application with WPF

Sometimes you need to have an application running in the background. Then you don’t want your MainWindow to be visible all the time. Instead you just want to have an icon in the notification area that allows the user to open up the MainWindow and to exit the application. In WPF you can do this easily with the help of Windows Forms’ NotifyIcon-class.

Just add references to System.Windows.Forms and System.Drawing to your WPF-project. Add also an icon-file (.ico) to your project resources. To do this just open the Resources.resx-file in the Properties-folder of your project. Select the Icon-resource and click the Add Resource button. I’ve named it MyIcon.

AddIconToResources

Then go to the App.xaml.cs and implement it like below. The trick is to never close the MainWindow, as a closed Window cannot be shown again. Instead cancel the closing and just hide it.

using System.ComponentModel;
using System.Windows;
 
namespace BackgroundApplication
{
 
    public partial class App : Application
    {
        private System.Windows.Forms.NotifyIcon _notifyIcon;
        private bool _isExit;
 
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            MainWindow = new MainWindow();
            MainWindow.Closing += MainWindow_Closing;
 
            _notifyIcon = new System.Windows.Forms.NotifyIcon();
            _notifyIcon.DoubleClick += (s, args) => ShowMainWindow();
            _notifyIcon.Icon = BackgroundApplication.Properties.Resources.MyIcon;
            _notifyIcon.Visible = true;
 
            CreateContextMenu();
        }
 
        private void CreateContextMenu()
        {
            _notifyIcon.ContextMenuStrip =
              new System.Windows.Forms.ContextMenuStrip();
            _notifyIcon.ContextMenuStrip.Items.Add("MainWindow...").Click += (s, e) => ShowMainWindow();
            _notifyIcon.ContextMenuStrip.Items.Add("Exit").Click += (s, e) => ExitApplication();
        }
 
        private void ExitApplication()
        {
            _isExit = true;
            MainWindow.Close();
            _notifyIcon.Dispose();
            _notifyIcon = null;
        }
 
        private void ShowMainWindow()
        {
            if (MainWindow.IsVisible)
            {
                if (MainWindow.WindowState == WindowState.Minimized)
                {
                    MainWindow.WindowState = WindowState.Normal;
                }
                MainWindow.Activate();
            }
            else
            {
                MainWindow.Show();
            }
        }
 
        private void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            if (!_isExit)
            {
                e.Cancel = true;
                MainWindow.Hide(); // A hidden window can be shown again, a closed one not
            }
        }
    }
}

Now go in addition to the App.xaml and remove the Startup-Uri, so that when you start the application, only the NotifyIcon is added to the notification area

<Application x:Class="BackgroundApplication.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:BackgroundApplication">
  <Application.Resources>
         
    </Application.Resources>
</Application>

Done

Download the sample-project here: Background application

Share this post

Comments (36)

  • Apyn AOM Reply

    Thanks again ! Very fast and easy solution
    Personnaly, I use this code to set an icon :
    _notifyIcon.Icon = Propeties.Resources.MyIcon;
    After having add the icon in Project Propeties, tab Resources ;)

    August 22, 2015 at 12:47 pm
    • Thomas Claudius Huber Reply

      Jep, that’s more the Windows Forms way and great. Thanks. I’ve adjusted it in the Blog-post. :-)

      August 22, 2015 at 1:00 pm
  • Jiya Reply

    Hi,
    Great Article. It helped a lot. But i have a question.
    Since _notifyIcon is in App.xml.cs file, How to i access it in MainWindow.cs file ?
    I tried making _notifyIcon public and then tried to access it like App._notifyIcon , but property was not listed.

    When some activity happens, I want to show ShowBalloonTip from Mainwindow.cs

    please advice

    Regards
    Jiya

    March 10, 2017 at 7:23 pm
    • Thomas Claudius Huber Reply

      Hi Jiya, thanks. If you want to acces the variable, I recommend you to create a public readonly property in App.xaml.cs:

      public System.Windows.Forms.NotifyIcon NotifyIcon { get { return _notifyIcon; } }

      Then you can use it in your MainWindow like this:

      ((App)App.Current).NotifyIcon

      March 14, 2017 at 10:22 pm
  • Santiago Reply

    It works even in Windows 10, great!!!

    The only caveat is that the NotifyIcon stays in the system tray even after the application is closed, and disappears only when the system tray is reopened. To avoid it, just set the Visible property to false before disposing the NotifyIcon.

    Thank you very much.

    June 1, 2017 at 1:13 pm
    • Thomas Claudius Huber Reply

      Hi Santiago,
      you’re welcome. Thanks for the feedback, great to hear it works in Windows 10 as well. :)

      June 8, 2017 at 11:19 am
  • Jerome C. Reply

    How do you quit this application from an exit menu in the MainWindow ? Also is it posible to ask for a confirmation before exiting the application ? Thanks !

    May 5, 2018 at 8:06 pm
  • Russ Lynch Reply

    The application quits after 50-60 minutes of execution time… The icon is left on the desktop; it disappears on mouse over. Please advise.

    June 3, 2018 at 9:01 pm
  • Russ Lynch Reply

    There is no problem with your application at all. In my implementation I created a bitmap icon and neglected to destroy it, causing a memory leak. I have corrected my program, and it is working now. Thank you for an excellent easy to follow example. -RL

    June 4, 2018 at 6:18 pm
    • Thomas Claudius Huber Reply

      Hi Russ,

      thanks for coming back.

      I’m happy to read that it’s working now.
      Thomas

      June 5, 2018 at 1:52 pm
  • Christian Larsson Reply

    Thank you very much for this easy guide! :)

    October 13, 2018 at 12:39 pm
  • TCHATCHEDRE Ziyaad Reply

    thank’s a lot.. your tutorial is well explained. sorry for my bad english

    February 19, 2019 at 10:01 am
  • Vitaliy Reply

    if you use MainWindow = new MainWindow (); in App, it’s easier to call all your code in MainWindow.xaml.cs and there after InitializeComponent () execute MainWindows.Hide (), will be the same. What’s the point?

    March 14, 2019 at 2:50 pm
    • Thomas Claudius Huber Reply

      Hi Vitaliy,

      that’s not the same. If you call MainWindow.Hide() in the constructor after InitializeComponent, it will work exactly one time at start up. But when you open and close the Window, then it’s gone. You need to call the Hide method in the Closing event that occurs everytime the user tries to close the Window.

      Of course you could implement the event handler for the Closing event in the MainWindow.xaml.cs file, but the code of this post gives you a solution where you don’t have to touch the MainWindow at all.

      Cheers,
      Thomas

      March 23, 2019 at 1:26 pm
  • Zrus Reply

    Thanks for your easy guide. But while I open it, I want it open the mainwindow, so do I need to keep Start-upUri? And if it’s necessary to keep, how can I still run it in background? Thanks a lot.

    August 12, 2019 at 2:44 pm
    • Thomas Claudius Huber Reply

      At the end of the OnStartup method, just call ShowMainWindow, and you’re done.

      Cheers,
      Thomas

      September 12, 2019 at 10:11 am
  • mm Reply

    Thanks, works perfectly!

    September 23, 2019 at 5:16 pm
  • Rick Reply

    Why do you no use ShutdownMode=”OnExplicitShutdown” in app.xaml ?

    October 11, 2019 at 2:52 pm
  • Alexey Vovchenko Reply

    Amaizing and so simple guide. Many thanks, God bless you, man

    May 4, 2020 at 10:59 am
  • Sanket K Reply

    Thanks! Really helpful and well explained. How can I show notifications/bubbles from the system tray? Can you just point to what I should use?

    November 4, 2020 at 5:31 pm
  • Divyashri Reply

    Thanks a lot for this post! It works perfectly in .net framework but when I tried same on .net core the application is not running in backgound.Can you please advice?

    December 3, 2020 at 2:41 pm
    • Thomas Claudius Huber Reply

      Hi Divyashri, haven’t tried this yet. Do you still have the problem?

      December 21, 2020 at 3:19 pm
    • sunil Reply

      @Divyashi,

      You have to add true in to your “.csproj” file then it will work for the .Net project also.

      Thanks,

      April 13, 2022 at 1:06 pm
      • sunil Reply

        Please add ” true” in “.csproj” to work with .net Core

        April 13, 2022 at 1:08 pm
  • Stefan Reply

    Hi Thomas, thank you for this guide. I dont have an icon so I ignored the icon property of _notifyIcon and I set the Text property (_notifyIcon.Text = “My application”). Should it to be the same? After starting my application nothing is showed on systray. Can you help?

    December 5, 2020 at 6:34 pm
    • Thomas Claudius Huber Reply

      Hi Stefan,

      haven’t tried it without Icon. Did you try if it works when you’re using an icon?

      December 21, 2020 at 3:18 pm
  • Umar Reply

    Hi Thomas,
    Thank you for this article. I have implemented this in one of my applications. It works great but there is one side effect of it. Now, the app is running in the background only. The next time, I want to open the app, I forget that it is running in the background and I can open it from there. So, I just double-click its icon on the desktop and a new instance of the app opens up.
    I was able to check if that app is already running, but I couldn’t bring it to the front. I found a solution that used to calling unmanaged code through DllImport stuff but it doesn’t work most of the time, its behavior was pretty random and it worked a couple of times.
    Kindly, suggest a solution for that.
    Thank you.

    April 9, 2021 at 8:01 pm
  • sunil Reply

    Hi Thomas,
    Thank you for this great guide, I have observed that most of the tray icon open if you just do a single click but here in your shared code it will work only if we do double click (notifyIcon.DoubleClick += (s, args) => ShowMainWindow();)

    However, I tried notifyIcon.MouseClick += (s, args) => ShowMainWindow(); but here problem is , it will open the main windows even if I will do just right click for the context menu.
    So, could you please provide the suggestion to avoid the opening of main windows while doing the mouse right click and single click open of of the main windows while clicking on the tray icon

    Thank you,
    Sunil

    April 6, 2022 at 5:01 pm
  • sunil Reply

    Hi Thomas,

    I observed an issue in this, like when I execute the code it launches the main window and also creates the icon in the system tray, But if immediately without closing the window if I do double click on the system tray icon it opens another window (now total 2 windows )along with the existing windows.
    Because in function private void ShowMainWindow()—>
    if (MainWindow.IsVisible) –> is coming as “false” hence it is calling else part and launching another windows.

    Could you please help me here, so that only one window must be created?

    Thanks,
    Sunil

    April 21, 2022 at 8:08 pm
  • sunil Reply

    Hi Thomas,

    I observed that once we launch the app it opens the main windows and also create the system tray icons.
    and if I keep open the main window and double click the system tray icon it opens another instance of the main window because if (MainWindow.IsVisible) – is coming as false so it is executing the else part and showing the 2nd window.

    could you please help me here to solve the opening of the 2nd window after double click .

    Regards,
    Sunil

    April 22, 2022 at 6:03 pm

Leave a Reply to mm Cancel reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.