Иконка в системном трее Windows в качестве службы - PullRequest
0 голосов
/ 14 октября 2019

Я создал приложение Python, которое работает как служба и имеет значок в системном трее (для Windows). Я использую wxPython в качестве программы-оболочки, которая вызывает основную программу как поток. Проблема в том, что когда я запускаю программу как службу, запускается основная программа, но значок на панели задач не создается.

Я прочитал, что создание значка на панели задач в качестве службы Windows не идеально, но снованашел противоречивую информацию по этой теме.

Вот мой код:

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import sys,os,time

#// Wx
import wx.adv
import wx #pip install wxpython
from wx.lib.embeddedimage import PyEmbeddedImage
from threading import Thread
#from pubsub import pub #pip install PyPubSub

TRAY_TOOLTIP = 'test5' 
get_python_logo = PyEmbeddedImage(
    "iVBORw0KGgoAAAANSUhEUgAAAA4AAAATCAIAAAAvYqvDAAAAA3NCSVQICAjb4U/gAAACjUlE"
    "QVQokQXBW4/bRBgA0G++ufhux068abaQUvUmASovCHhC/HOe+oCQkFYVSKjbVQXsshuycXwb"
    "ezw3ziH+6idvUJuAh/VvVzd5eRnnZZSEd7efpDx+9/3bqbnjTlL0CGb2oAk6QmxepFkeE2LP"
    "5+N6U4QRs1NvnaKUEOoRqEXugWhtZLEKt0/K9ToLAnJRr7JEDGNjnSTcADUMGAWky2SHvmO8"
    "IkkS8OiCI01FnKVSdWnIgFBvFvSGg4+8j8bJAY3BBoApj9bgwizbeh8xkQGJnAtRQ+BJyKKc"
    "iixbbZ1DWKzSRC1OJOXiqYXAeO5pwJRDpeys7eSBRInUYLRarAGvs1SchplwSATEgrNOlvPs"
    "hgnPHb3Ylf0EljBPnLMRE+Gxib0TJuEkT5jsv3z1w4+Q1Nfv3lPyYplkulpruwBZ5DC//erZ"
    "k69fwPnhz19/YY4I1/QY7F5+8y3Eu+JlAMDAG6AWpkfABaax/fcxiHKG0c0fH2/Ebb17+gb6"
    "CnnqgRFOEJbT6bbM+afr983hr/3TLbu8hA8f/0Yzns+2H3FxQVHVSs9q7gJhtVqiqGvxfrNZ"
    "ITNtTOTr/Trmc5l4XJp1CqgbNx3rgk6nf54/r8vEE92wpW+dHP0sz3cd0NXcqhB8wvixeZxz"
    "1h4OMG5xnuSpYVm8qUI7n2ZhuHeiCmOxsIt4M4SV792zej89DIUoC5oysF5Q1Mvw+RdvnKsN"
    "xNp5RNx/9kqOD+vX9eHqXcgpsQYBVFZQzx/vTx/u207s9hNTPUw83RRVebj+edS/F5XFAhjo"
    "AVCj0NapblTpeWjGkVOm1GRVi7QNMgU4AY0QnKEMw1AgopTzuem7VqrZ9d18/K9FEuZZ5ZwD"
    "5/4H45tv6Xt4MTIAAAAASUVORK5CYII=")

def create_menu_item(menu, label, func):
    item = wx.MenuItem(menu, -1, label)
    menu.Bind(wx.EVT_MENU, func, id=item.GetId())
    menu.Append(item)
    return item

class ProgramThread(Thread):
    """Worker Thread Class."""

    def __init__(self):
        """Init Worker Thread Class."""
        Thread.__init__(self)
        self.setDaemon(True)
        self.start()    # start the thread

    def run(self):
        """Run Worker Thread."""
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(AppServerSvc)
        servicemanager.StartServiceCtrlDispatcher()    

class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "test5"
    _svc_display_name_ = "test5"
    _svc_description_name_ = "test5"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)

    def SvcStop(self):
        #wx.CallAfter(pub.sendMessage, "exit", event="exit")
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)

    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,'Attemping to Start the Service.'))
        self.main()

    def main(self):
        while True:
            print 1

class TaskBarIcon(wx.adv.TaskBarIcon):
    def __init__(self, frame):
        self.frame = frame
        super(TaskBarIcon, self).__init__()
        self.set_icon(get_python_logo.GetIcon())

        self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.on_left_down)

        # create a pubsub receiver
        #pub.subscribe(self.on_exit, "exit")    

        ProgramThread()        

    def CreatePopupMenu(self):
        menu = wx.Menu()
        create_menu_item(menu, 'Site', self.on_hello)
        menu.AppendSeparator()
        create_menu_item(menu, 'Exit', self.on_exit)
        return menu

    def set_icon(self, path):
        print "set icon"
        icon = wx.Icon(path)
        self.SetIcon(icon, TRAY_TOOLTIP)

    def on_left_down(self, event):
        print ('Tray icon was left-clicked.')

    def on_hello(self, event):
        print ('Hello, world!')

    def on_exit(self, event):
        wx.CallAfter(self.Destroy)
        self.frame.Close()        

class App(wx.App):
    def OnInit(self):
        frame=wx.Frame(None)
        self.SetTopWindow(frame)
        TaskBarIcon(frame)
        return True

# Run the program
if __name__ == "__main__":
    #// Whether called by user or service manager
    if len(sys.argv) == 1:
        app = App(False)
        app.MainLoop()
    else:
        win32serviceutil.HandleCommandLine(AppServerSvc)
...