Pystray icon available when running as a service

1.3k Views Asked by At

Using:

  • Python (3.7.5)
  • Pyinstaller (3.5)
  • Pywin32 (223)
  • Pystray (Current)

I have a python program that uses Pystray to show an icon which allows me to make Tkinter window available. It took a while but, thanks to stack overflow, this functionality works fine. I then create an executable for this using PyInstaller and this also runs fine. Up to here everything is great, executing the program starts its webservice and shows the icon.

I call this program from a service created with pywin32. The program starts as expected, and it's webservice functionality is available, however I cannot see the system tray icon. I assume this is because I am logged in as an administrator, but the service runs under the general service account.

Is there any way to make the Pystray Icon available to all users logged into the machine?

1

There are 1 best solutions below

0
On

This link explains it all : https://learn.microsoft.com/en-us/archive/blogs/winsdk/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later

Abstract : You cannot open an interactive process from a windows service as you normally would, cause the service runs on a totally different environment ( aka Session 0 ) while the logged-in user's session id is 1...2... depending upon the number of users.

if you start your service and look at the 'Details' tab in Task Manager you'll find your process running but not showing up

from what i understood, here we ( i too encountered the exact same problem after a while ) are trying to open a process from a service that is in session 0 and it cannot interact with session 1 directly ? so we should create the new process as a user using CreateProcessAsUser

i used the following code to get it running :

# A SETUP FOR STARTUPINFO
startupInfo = win32process.STARTUPINFO()
startupInfo.dwFlags = win32process.STARTF_USESHOWWINDOW
startupInfo.wShowWindow = win32con.SW_NORMAL

# GET THE TOKEN FOR LOGGED-IN USER
console_session_id = win32ts.WTSGetActiveConsoleSessionId()
console_user_token = win32ts.WTSQueryUserToken(console_session_id)
# GET THE LOGGED IN USER'S ENVIRONMENT TOO
environment = win32profile.CreateEnvironmentBlock(console_user_token, False)

win32process.CreateProcessAsUser(console_user_token,
                                 'notepad.exe', # PATH TO YOUR EXECUTABLE / SCRIPT
                                 None, # THIS ONE IS 'COMMAND LINE' IF YOU INTEND YOU USE IT
                                 None,
                                 None,
                                 0,
                                 win32con.NORMAL_PRIORITY_CLASS,
                                 environment, # TO OPEN IN USER'S ENVIRONMENT
                                 None,
                                 startupInfo)

Let me know if you have any queries