0

I have a C# service (.NET 4.6.2) that polls an online API. Tied to that is also a tray icon. The service is supposed to keep the tray icon running, and the icon is supposed to keep the service running.

If the service has to restart the tray icon for any reason, then it does, but the icon doesn't come back. I am trying to solve that because the users think that if the icon isn't there that it isn't working. When they restart the application and get the icon back, it runs through this:

 Process process = Process.GetCurrentProcess();
        var dupl = (Process.GetProcessesByName(process.ProcessName));
        if (dupl.Length > 1)
        {
            foreach (var p in dupl)
            {
                if (p.Id != process.Id)
                    p.Kill();
            }
        }

to make sure there is only a single copy at any one time. I realize that services aren't supposed to access the UI directly, but isn't there an indirect method? Can I do it by passing my call through another DLL or something?

I have looked into this quite a bit and find so many resources that end up being outdated. Even this one from last year, which seemed promising doesn't work. How to create process as user with arguments

This service is deployed on computers from Windows 32bit to Windows 10. There is not always a user logged in, but let's assume for simplicity's sake that there is and I can error handle the rest later.

Alan
  • 2,046
  • 2
  • 20
  • 43

1 Answers1

1

Indeed, your service is not supposed to interact with a user and if you find an article that sports a hack on how to do it anyway, it's bound to fail sooner or later.

The correct way to do it is to have two applications. A service and a user interface. The service runs as a service. The user interface app is started as the user (maybe from their autostart). Then those two applications communicate via some kind of IPC, maybe sockets or pipes. The user interface can display a tray icon and display status messages it gets from the service or it can send commands to the service that it gets from the user via for example the tray icons context menu.

So do not try to fake a solution. It will not work properly, because it's not supposed to work properly. Build two applications.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • Should I then have a 3rd application that monitors both? I also need to be able to start TightVNC from the service to initiate an outgoing remote session in response to the API calls – Alan Mar 05 '19 at 17:15
  • Or maybe more simply put, TightVNC, Teamviewer, LogMeIn are all services. When they run, they have access to respond to incoming TCP requests which gives them access to the desktop and change tray icon colors, provide notifications and such. They accomplish all of this even when the only thing that loads on startup is the service. – Alan Mar 05 '19 at 17:18
  • How would a VNC service know what desktop to show if I open 3 desktops in windows 10? I'm pretty sure you will find a piece of code that is running in the users session for all of them. To be honest I don't know what it looks like because I don't know those three programs internals, but there will be. There is no magic way to determine which desktop to pick. – nvoigt Mar 05 '19 at 17:23
  • But are you saying if I did know the desktop I could send it there? Isn't that something that could be scripted using WMI? – Alan Mar 05 '19 at 17:37
  • 1
    To be honest, I don't know. The official reading is that you should not access a user's desktop from a windows service directly, so I never bothered to check if there are hacks to get around the official guideline. – nvoigt Mar 06 '19 at 09:08