123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- # ControlService.py
- #
- # A simple app which duplicates some of the functionality in the
- # Services applet of the control panel.
- #
- # Suggested enhancements (in no particular order):
- #
- # 1. When changing the service status, continue to query the status
- # of the service until the status change is complete. Use this
- # information to put up some kind of a progress dialog like the CP
- # applet does. Unlike the CP, allow canceling out in the event that
- # the status change hangs.
- # 2. When starting or stopping a service with dependencies, alert
- # the user about the dependent services, then start (or stop) all
- # dependent services as appropriate.
- # 3. Allow toggling between service view and device view
- # 4. Allow configuration of other service parameters such as startup
- # name and password.
- # 5. Allow connection to remote SCMs. This is just a matter of
- # reconnecting to the SCM on the remote machine; the rest of the
- # code should still work the same.
- # 6. Either implement the startup parameters or get rid of the editbox.
- # 7. Either implement or get rid of "H/W Profiles".
- # 8. Either implement or get rid of "Help".
- # 9. Improve error handling. Ideally, this would also include falling
- # back to lower levels of functionality for users with less rights.
- # Right now, we always try to get all the rights and fail when we can't
- from pywin.mfc import dialog
- import win32ui
- import win32con
- import win32service
- class StartupDlg(dialog.Dialog):
- IDC_LABEL = 127
- IDC_DEVICE = 128
- IDC_BOOT = 129
- IDC_SYSTEM = 130
- IDC_AUTOMATIC = 131
- IDC_MANUAL = 132
- IDC_DISABLED = 133
- def __init__(self, displayname, service):
- dialog.Dialog.__init__(self, self.GetResource())
- self.name = displayname
- self.service = service
- def __del__(self):
- win32service.CloseServiceHandle(self.service)
- def OnInitDialog(self):
- cfg = win32service.QueryServiceConfig(self.service)
- self.GetDlgItem(self.IDC_BOOT + cfg[1]).SetCheck(1)
- status = win32service.QueryServiceStatus(self.service)
- if ((status[0] & win32service.SERVICE_KERNEL_DRIVER) or
- (status[0] & win32service.SERVICE_FILE_SYSTEM_DRIVER)):
- # driver
- self.GetDlgItem(self.IDC_LABEL).SetWindowText('Device:')
- else:
- # service
- self.GetDlgItem(self.IDC_LABEL).SetWindowText('Service:')
- self.GetDlgItem(self.IDC_BOOT).EnableWindow(0)
- self.GetDlgItem(self.IDC_SYSTEM).EnableWindow(0)
- self.GetDlgItem(self.IDC_DEVICE).SetWindowText(str(self.name))
- return dialog.Dialog.OnInitDialog(self)
- def OnOK(self):
- self.BeginWaitCursor()
- starttype = self.GetCheckedRadioButton(self.IDC_BOOT, self.IDC_DISABLED) - self.IDC_BOOT
- try:
- win32service.ChangeServiceConfig(self.service, win32service.SERVICE_NO_CHANGE, starttype,
- win32service.SERVICE_NO_CHANGE, None, None, 0, None, None, None, None)
- except:
- self.MessageBox('Unable to change startup configuration', None,
- win32con.MB_ICONEXCLAMATION)
- self.EndWaitCursor()
- return dialog.Dialog.OnOK(self)
- def GetResource(self):
- style = win32con.WS_POPUP | win32con.DS_SETFONT | win32con.WS_SYSMENU | win32con.WS_CAPTION | win32con.WS_VISIBLE | win32con.DS_MODALFRAME
- exstyle = None
- t = [["Service Startup", (6, 18, 188, 107), style, exstyle, (8, 'MS Shell Dlg')], ]
- t.append([130, "Device:", self.IDC_LABEL, (6, 7, 40, 8), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT])
- t.append([130, "", self.IDC_DEVICE, (48, 7, 134, 8), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT])
- t.append([128, "Startup Type", -1, (6, 21, 130, 80), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_GROUP | win32con.BS_GROUPBOX])
- t.append([128, "&Boot", self.IDC_BOOT, (12, 33, 39, 10), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_AUTORADIOBUTTON])
- t.append([128, "&System", self.IDC_SYSTEM, (12, 46, 39, 10), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_AUTORADIOBUTTON])
- t.append([128, "&Automatic", self.IDC_AUTOMATIC, (12, 59, 118, 10), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_AUTORADIOBUTTON])
- t.append([128, "&Manual", self.IDC_MANUAL, (12, 72, 118, 10), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_AUTORADIOBUTTON])
- t.append([128, "&Disabled", self.IDC_DISABLED, (12, 85, 118, 10), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_AUTORADIOBUTTON])
- t.append([128, "OK", win32con.IDOK, (142, 25, 40, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.WS_GROUP | win32con.BS_DEFPUSHBUTTON])
- t.append([128, "Cancel", win32con.IDCANCEL, (142, 43, 40, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([128, "&Help", win32con.IDHELP, (142, 61, 40, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- return t
- class ServiceDlg(dialog.Dialog):
- IDC_LIST = 128
- IDC_START = 129
- IDC_STOP = 130
- IDC_PAUSE = 131
- IDC_CONTINUE = 132
- IDC_STARTUP = 133
- IDC_PROFILES = 134
- IDC_PARAMS = 135
- def __init__(self, machineName = ''):
- dialog.Dialog.__init__(self, self.GetResource())
- self.HookCommand(self.OnListEvent, self.IDC_LIST)
- self.HookCommand(self.OnStartCmd, self.IDC_START)
- self.HookCommand(self.OnStopCmd, self.IDC_STOP)
- self.HookCommand(self.OnPauseCmd, self.IDC_PAUSE)
- self.HookCommand(self.OnContinueCmd, self.IDC_CONTINUE)
- self.HookCommand(self.OnStartupCmd, self.IDC_STARTUP)
- self.machineName = machineName
- self.scm = win32service.OpenSCManager(self.machineName, None, win32service.SC_MANAGER_ALL_ACCESS)
- def __del__(self):
- win32service.CloseServiceHandle(self.scm)
- def OnInitDialog(self):
- self.listCtrl = self.GetDlgItem(self.IDC_LIST)
- self.listCtrl.SetTabStops([158, 200])
- if self.machineName:
- self.SetWindowText("Services on %s" % self.machineName)
- self.ReloadData()
- return dialog.Dialog.OnInitDialog(self)
- def ReloadData(self):
- service = self.GetSelService()
- self.listCtrl.SetRedraw(0)
- self.listCtrl.ResetContent()
- svcs = win32service.EnumServicesStatus(self.scm)
- i = 0
- self.data = []
- for svc in svcs:
- try:
- status = ('Unknown', 'Stopped', 'Starting', 'Stopping', 'Running',
- 'Continuing', 'Pausing', 'Paused')[svc[2][1]]
- except:
- status = 'Unknown'
- s = win32service.OpenService(self.scm, svc[0], win32service.SERVICE_ALL_ACCESS)
- cfg = win32service.QueryServiceConfig(s)
- try:
- startup = ('Boot', 'System', 'Automatic', 'Manual', 'Disabled')[cfg[1]]
- except:
- startup = 'Unknown'
- win32service.CloseServiceHandle(s)
- # svc[2][2] control buttons
- pos = self.listCtrl.AddString(str(svc[1]) + '\t' + status + '\t' + startup)
- self.listCtrl.SetItemData(pos, i)
- self.data.append(tuple(svc[2]) + (svc[1], svc[0], ))
- i = i + 1
- if service and service[1] == svc[0]:
- self.listCtrl.SetCurSel(pos)
- self.OnListEvent(self.IDC_LIST, win32con.LBN_SELCHANGE)
- self.listCtrl.SetRedraw(1)
- def OnListEvent(self, id, code):
- if code == win32con.LBN_SELCHANGE or code == win32con.LBN_SELCANCEL:
- pos = self.listCtrl.GetCurSel()
- if pos >= 0:
- data = self.data[self.listCtrl.GetItemData(pos)][2]
- canstart = (self.data[self.listCtrl.GetItemData(pos)][1] == win32service.SERVICE_STOPPED)
- else:
- data = 0
- canstart = 0
- self.GetDlgItem(self.IDC_START).EnableWindow(canstart)
- self.GetDlgItem(self.IDC_STOP).EnableWindow(data & win32service.SERVICE_ACCEPT_STOP)
- self.GetDlgItem(self.IDC_PAUSE).EnableWindow(data & win32service.SERVICE_ACCEPT_PAUSE_CONTINUE)
- self.GetDlgItem(self.IDC_CONTINUE).EnableWindow(data & win32service.SERVICE_ACCEPT_PAUSE_CONTINUE)
- def GetSelService(self):
- pos = self.listCtrl.GetCurSel()
- if pos < 0:
- return None
- pos = self.listCtrl.GetItemData(pos)
- return self.data[pos][-2:]
- def OnStartCmd(self, id, code):
- service = self.GetSelService()
- if not service:
- return
- s = win32service.OpenService(self.scm, service[1], win32service.SERVICE_ALL_ACCESS)
- win32service.StartService(s, None)
- win32service.CloseServiceHandle(s)
- self.ReloadData()
- def OnStopCmd(self, id, code):
- service = self.GetSelService()
- if not service:
- return
- s = win32service.OpenService(self.scm, service[1], win32service.SERVICE_ALL_ACCESS)
- win32service.ControlService(s, win32service.SERVICE_CONTROL_STOP)
- win32service.CloseServiceHandle(s)
- self.ReloadData()
- def OnPauseCmd(self, id, code):
- service = self.GetSelService()
- if not service:
- return
- s = win32service.OpenService(self.scm, service[1], win32service.SERVICE_ALL_ACCESS)
- win32service.ControlService(s, win32service.SERVICE_CONTROL_PAUSE)
- win32service.CloseServiceHandle(s)
- self.ReloadData()
- def OnContinueCmd(self, id, code):
- service = self.GetSelService()
- if not service:
- return
- s = win32service.OpenService(self.scm, service[1], win32service.SERVICE_ALL_ACCESS)
- win32service.ControlService(s, win32service.SERVICE_CONTROL_CONTINUE)
- win32service.CloseServiceHandle(s)
- self.ReloadData()
- def OnStartupCmd(self, id, code):
- service = self.GetSelService()
- if not service:
- return
- s = win32service.OpenService(self.scm, service[1], win32service.SERVICE_ALL_ACCESS)
- if StartupDlg(service[0], s).DoModal() == win32con.IDOK:
- self.ReloadData()
- def GetResource(self):
- style = win32con.WS_POPUP | win32con.DS_SETFONT | win32con.WS_SYSMENU | win32con.WS_CAPTION | win32con.WS_VISIBLE | win32con.DS_MODALFRAME
- exstyle = None
- t = [["Services", (16, 16, 333, 157), style, exstyle, (8, 'MS Shell Dlg')], ]
- t.append([130, "Ser&vice", -1, (6, 6, 70, 8), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT])
- t.append([130, "Status", -1, (164, 6, 42, 8), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT])
- t.append([130, "Startup", -1, (206, 6, 50, 8), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT])
- t.append([131, "", self.IDC_LIST, (6, 16, 255, 106), win32con.LBS_USETABSTOPS | win32con.LBS_SORT | win32con.LBS_NOINTEGRALHEIGHT | win32con.WS_BORDER | win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_TABSTOP | win32con.LBS_NOTIFY | win32con.WS_VSCROLL])
- t.append([128, "Close", win32con.IDOK, (267, 6, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_GROUP | win32con.WS_TABSTOP | win32con.BS_DEFPUSHBUTTON])
- t.append([128, "&Start", self.IDC_START, (267, 27, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([128, "S&top", self.IDC_STOP, (267, 44, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([128, "&Pause", self.IDC_PAUSE, (267, 61, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([128, "&Continue", self.IDC_CONTINUE, (267, 78, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([128, "Sta&rtup...", self.IDC_STARTUP, (267, 99, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([128, "H&W Profiles...", self.IDC_PROFILES, (267, 116, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([128, "&Help", win32con.IDHELP, (267, 137, 60, 14), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_TABSTOP | win32con.BS_PUSHBUTTON])
- t.append([130, "St&artup Parameters:", -1, (6, 128, 70, 8), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT])
- t.append([129, "", self.IDC_PARAMS, (6, 139, 247, 12), win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.WS_GROUP | win32con.WS_BORDER | win32con.ES_AUTOHSCROLL])
- return t
- if __name__=='__main__':
- import sys
- machine = ''
- if len(sys.argv)>1:
- machine = sys.argv[1]
- ServiceDlg(machine).DoModal()
|