1

I'm familiar with writing windows service applications. I've written a few using various approaches - third party libs, the .NET-provided approach, etc. None of my prior service applications had any way to interact with them, though.

I'm needing now to write a windows service application, but it will need a task tray icon that perhaps brings up a "management GUI" when you click on it.

What is the appropriate pattern for doing this?

Should the service be its own application, but is able to be interacted with through external means - perhaps a database that it polls for config changes? Should it use IPC or something?

Is there a way to make a windows service also have a GUI so that the management GUI and the service are all just the same application?

Ryan
  • 7,733
  • 10
  • 61
  • 106
  • Windows services are designed to run headless; with no UI. If you want a UI you have to write a GUI app; like WinForms, WPF, UWP. Decide whether you want the GUI app to do whatever your service does, or whether your GUI app should send data to your service. – Dour High Arch Feb 05 '19 at 18:12
  • Actually a service can hardly access to UI as it may run even if noone is logged in. Plus, it usually runs with Local System or Network Service which has more restriction than normal account. I think the best pattern is to have another application independent from the original service to perform the management & the GUI role. – Perfect28 Feb 05 '19 at 18:12

2 Answers2

3

Is there a way to make a windows service also have a GUI

No; a windows service doesn't have an (interactive) desktop by definition. Anything that points to getting that to work will be a very dirty hack at the very best.

Is there a way to make a windows service also have a GUI so that the management GUI and the service are all just the same application?

You can share code by putting common stuff in a library or something. You can even share the entire codebase and run the application with an --service commandline argument (for example) and the GUI part without (or with --gui) argument(s).

interacted with through external means - perhaps a database that it polls for config changes?

That is a possibility but not the fastest or most efficient

Should it use IPC or something?

I would opt for that. You can use whatever you want; a REST API, WCF, TCP/UDP connections, sockets, (named) pipes, memory mapped I/O... whatever you choose, it will be some sort of IPC. You can even send custom commands to your service but that is very, very limited.

If it were up to my I'd implement it using WCF. But I'm kinda biased, I do lots of WCF stuff.

RobIII
  • 8,488
  • 2
  • 43
  • 93
2

Summary

Yes, your Windows service can have a GUI. However, that GUI has to be a separate project (say a Windows Forms project). It's just that the Windows Forms project and your Windows service project have to use whatever is common in between such as database, APIs (e.g. WCF), library, etc. Typically, you would carry out the necessary functionality inside your Windows service and update state / settings in your Windows Forms application.

Adding Your GUI to Task Tray along with a Shortcut Menu

In the Main method of your Windows Forms application, create an object of the NotifyIcon class. You can also create a ContextMenu object and assign it to the ContextMenu property of the NotifyIcon object to allow the tray icon to have shortcut menu. Here is a sample:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    using (var icon = new NotifyIcon())
    {
        icon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath);

        var contextMenu = new ContextMenu();
        var mnuProperties = new MenuItem()
        {
            Text = "Properties"
        };
        var mnuQuit = new MenuItem()
        {
            Text = "Quit"
        };

        mnuProperties.Click += mnuProperties_Click;
        mnuQuit.Click += mnuQuit_Click;

        contextMenu.MenuItems.Add(mnuProperties);
        contextMenu.MenuItems.Add(mnuQuit);

        icon.ContextMenu = contextMenu;
        icon.Visible = true;

        Application.Run();
    }
}

private static void mnuQuit_Click(object sender, EventArgs e)
{
    Application.Exit();
}

private static void mnuProperties_Click(object sender, EventArgs e)
{
    var propertiesForm = new PropertiesForm();
    propertiesForm.Show();
}

Needless to mention, you can add as many menu items to the context menu, add forms, etc.

One last point, it doesn't have to be a Windows Forms application. It can very well be a WPF application instead.

Tanveer Yousuf
  • 386
  • 1
  • 3
  • 16