Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ControlService.py 18KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. # ControlService.py
  2. #
  3. # A simple app which duplicates some of the functionality in the
  4. # Services applet of the control panel.
  5. #
  6. # Suggested enhancements (in no particular order):
  7. #
  8. # 1. When changing the service status, continue to query the status
  9. # of the service until the status change is complete. Use this
  10. # information to put up some kind of a progress dialog like the CP
  11. # applet does. Unlike the CP, allow canceling out in the event that
  12. # the status change hangs.
  13. # 2. When starting or stopping a service with dependencies, alert
  14. # the user about the dependent services, then start (or stop) all
  15. # dependent services as appropriate.
  16. # 3. Allow toggling between service view and device view
  17. # 4. Allow configuration of other service parameters such as startup
  18. # name and password.
  19. # 5. Allow connection to remote SCMs. This is just a matter of
  20. # reconnecting to the SCM on the remote machine; the rest of the
  21. # code should still work the same.
  22. # 6. Either implement the startup parameters or get rid of the editbox.
  23. # 7. Either implement or get rid of "H/W Profiles".
  24. # 8. Either implement or get rid of "Help".
  25. # 9. Improve error handling. Ideally, this would also include falling
  26. # back to lower levels of functionality for users with less rights.
  27. # Right now, we always try to get all the rights and fail when we can't
  28. import win32con
  29. import win32service
  30. import win32ui
  31. from pywin.mfc import dialog
  32. class StartupDlg(dialog.Dialog):
  33. IDC_LABEL = 127
  34. IDC_DEVICE = 128
  35. IDC_BOOT = 129
  36. IDC_SYSTEM = 130
  37. IDC_AUTOMATIC = 131
  38. IDC_MANUAL = 132
  39. IDC_DISABLED = 133
  40. def __init__(self, displayname, service):
  41. dialog.Dialog.__init__(self, self.GetResource())
  42. self.name = displayname
  43. self.service = service
  44. def __del__(self):
  45. win32service.CloseServiceHandle(self.service)
  46. def OnInitDialog(self):
  47. cfg = win32service.QueryServiceConfig(self.service)
  48. self.GetDlgItem(self.IDC_BOOT + cfg[1]).SetCheck(1)
  49. status = win32service.QueryServiceStatus(self.service)
  50. if (status[0] & win32service.SERVICE_KERNEL_DRIVER) or (
  51. status[0] & win32service.SERVICE_FILE_SYSTEM_DRIVER
  52. ):
  53. # driver
  54. self.GetDlgItem(self.IDC_LABEL).SetWindowText("Device:")
  55. else:
  56. # service
  57. self.GetDlgItem(self.IDC_LABEL).SetWindowText("Service:")
  58. self.GetDlgItem(self.IDC_BOOT).EnableWindow(0)
  59. self.GetDlgItem(self.IDC_SYSTEM).EnableWindow(0)
  60. self.GetDlgItem(self.IDC_DEVICE).SetWindowText(str(self.name))
  61. return dialog.Dialog.OnInitDialog(self)
  62. def OnOK(self):
  63. self.BeginWaitCursor()
  64. starttype = (
  65. self.GetCheckedRadioButton(self.IDC_BOOT, self.IDC_DISABLED) - self.IDC_BOOT
  66. )
  67. try:
  68. win32service.ChangeServiceConfig(
  69. self.service,
  70. win32service.SERVICE_NO_CHANGE,
  71. starttype,
  72. win32service.SERVICE_NO_CHANGE,
  73. None,
  74. None,
  75. 0,
  76. None,
  77. None,
  78. None,
  79. None,
  80. )
  81. except:
  82. self.MessageBox(
  83. "Unable to change startup configuration",
  84. None,
  85. win32con.MB_ICONEXCLAMATION,
  86. )
  87. self.EndWaitCursor()
  88. return dialog.Dialog.OnOK(self)
  89. def GetResource(self):
  90. style = (
  91. win32con.WS_POPUP
  92. | win32con.DS_SETFONT
  93. | win32con.WS_SYSMENU
  94. | win32con.WS_CAPTION
  95. | win32con.WS_VISIBLE
  96. | win32con.DS_MODALFRAME
  97. )
  98. exstyle = None
  99. t = [
  100. ["Service Startup", (6, 18, 188, 107), style, exstyle, (8, "MS Shell Dlg")],
  101. ]
  102. t.append(
  103. [
  104. 130,
  105. "Device:",
  106. self.IDC_LABEL,
  107. (6, 7, 40, 8),
  108. win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT,
  109. ]
  110. )
  111. t.append(
  112. [
  113. 130,
  114. "",
  115. self.IDC_DEVICE,
  116. (48, 7, 134, 8),
  117. win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT,
  118. ]
  119. )
  120. t.append(
  121. [
  122. 128,
  123. "Startup Type",
  124. -1,
  125. (6, 21, 130, 80),
  126. win32con.WS_VISIBLE
  127. | win32con.WS_CHILD
  128. | win32con.WS_GROUP
  129. | win32con.BS_GROUPBOX,
  130. ]
  131. )
  132. t.append(
  133. [
  134. 128,
  135. "&Boot",
  136. self.IDC_BOOT,
  137. (12, 33, 39, 10),
  138. win32con.WS_VISIBLE
  139. | win32con.WS_CHILD
  140. | win32con.WS_TABSTOP
  141. | win32con.BS_AUTORADIOBUTTON,
  142. ]
  143. )
  144. t.append(
  145. [
  146. 128,
  147. "&System",
  148. self.IDC_SYSTEM,
  149. (12, 46, 39, 10),
  150. win32con.WS_VISIBLE
  151. | win32con.WS_CHILD
  152. | win32con.WS_TABSTOP
  153. | win32con.BS_AUTORADIOBUTTON,
  154. ]
  155. )
  156. t.append(
  157. [
  158. 128,
  159. "&Automatic",
  160. self.IDC_AUTOMATIC,
  161. (12, 59, 118, 10),
  162. win32con.WS_VISIBLE
  163. | win32con.WS_CHILD
  164. | win32con.WS_TABSTOP
  165. | win32con.BS_AUTORADIOBUTTON,
  166. ]
  167. )
  168. t.append(
  169. [
  170. 128,
  171. "&Manual",
  172. self.IDC_MANUAL,
  173. (12, 72, 118, 10),
  174. win32con.WS_VISIBLE
  175. | win32con.WS_CHILD
  176. | win32con.WS_TABSTOP
  177. | win32con.BS_AUTORADIOBUTTON,
  178. ]
  179. )
  180. t.append(
  181. [
  182. 128,
  183. "&Disabled",
  184. self.IDC_DISABLED,
  185. (12, 85, 118, 10),
  186. win32con.WS_VISIBLE
  187. | win32con.WS_CHILD
  188. | win32con.WS_TABSTOP
  189. | win32con.BS_AUTORADIOBUTTON,
  190. ]
  191. )
  192. t.append(
  193. [
  194. 128,
  195. "OK",
  196. win32con.IDOK,
  197. (142, 25, 40, 14),
  198. win32con.WS_VISIBLE
  199. | win32con.WS_CHILD
  200. | win32con.WS_TABSTOP
  201. | win32con.WS_GROUP
  202. | win32con.BS_DEFPUSHBUTTON,
  203. ]
  204. )
  205. t.append(
  206. [
  207. 128,
  208. "Cancel",
  209. win32con.IDCANCEL,
  210. (142, 43, 40, 14),
  211. win32con.WS_VISIBLE
  212. | win32con.WS_CHILD
  213. | win32con.WS_TABSTOP
  214. | win32con.BS_PUSHBUTTON,
  215. ]
  216. )
  217. t.append(
  218. [
  219. 128,
  220. "&Help",
  221. win32con.IDHELP,
  222. (142, 61, 40, 14),
  223. win32con.WS_VISIBLE
  224. | win32con.WS_CHILD
  225. | win32con.WS_TABSTOP
  226. | win32con.BS_PUSHBUTTON,
  227. ]
  228. )
  229. return t
  230. class ServiceDlg(dialog.Dialog):
  231. IDC_LIST = 128
  232. IDC_START = 129
  233. IDC_STOP = 130
  234. IDC_PAUSE = 131
  235. IDC_CONTINUE = 132
  236. IDC_STARTUP = 133
  237. IDC_PROFILES = 134
  238. IDC_PARAMS = 135
  239. def __init__(self, machineName=""):
  240. dialog.Dialog.__init__(self, self.GetResource())
  241. self.HookCommand(self.OnListEvent, self.IDC_LIST)
  242. self.HookCommand(self.OnStartCmd, self.IDC_START)
  243. self.HookCommand(self.OnStopCmd, self.IDC_STOP)
  244. self.HookCommand(self.OnPauseCmd, self.IDC_PAUSE)
  245. self.HookCommand(self.OnContinueCmd, self.IDC_CONTINUE)
  246. self.HookCommand(self.OnStartupCmd, self.IDC_STARTUP)
  247. self.machineName = machineName
  248. self.scm = win32service.OpenSCManager(
  249. self.machineName, None, win32service.SC_MANAGER_ALL_ACCESS
  250. )
  251. def __del__(self):
  252. win32service.CloseServiceHandle(self.scm)
  253. def OnInitDialog(self):
  254. self.listCtrl = self.GetDlgItem(self.IDC_LIST)
  255. self.listCtrl.SetTabStops([158, 200])
  256. if self.machineName:
  257. self.SetWindowText("Services on %s" % self.machineName)
  258. self.ReloadData()
  259. return dialog.Dialog.OnInitDialog(self)
  260. def ReloadData(self):
  261. service = self.GetSelService()
  262. self.listCtrl.SetRedraw(0)
  263. self.listCtrl.ResetContent()
  264. svcs = win32service.EnumServicesStatus(self.scm)
  265. i = 0
  266. self.data = []
  267. for svc in svcs:
  268. try:
  269. status = (
  270. "Unknown",
  271. "Stopped",
  272. "Starting",
  273. "Stopping",
  274. "Running",
  275. "Continuing",
  276. "Pausing",
  277. "Paused",
  278. )[svc[2][1]]
  279. except:
  280. status = "Unknown"
  281. s = win32service.OpenService(
  282. self.scm, svc[0], win32service.SERVICE_ALL_ACCESS
  283. )
  284. cfg = win32service.QueryServiceConfig(s)
  285. try:
  286. startup = ("Boot", "System", "Automatic", "Manual", "Disabled")[cfg[1]]
  287. except:
  288. startup = "Unknown"
  289. win32service.CloseServiceHandle(s)
  290. # svc[2][2] control buttons
  291. pos = self.listCtrl.AddString(str(svc[1]) + "\t" + status + "\t" + startup)
  292. self.listCtrl.SetItemData(pos, i)
  293. self.data.append(
  294. tuple(svc[2])
  295. + (
  296. svc[1],
  297. svc[0],
  298. )
  299. )
  300. i = i + 1
  301. if service and service[1] == svc[0]:
  302. self.listCtrl.SetCurSel(pos)
  303. self.OnListEvent(self.IDC_LIST, win32con.LBN_SELCHANGE)
  304. self.listCtrl.SetRedraw(1)
  305. def OnListEvent(self, id, code):
  306. if code == win32con.LBN_SELCHANGE or code == win32con.LBN_SELCANCEL:
  307. pos = self.listCtrl.GetCurSel()
  308. if pos >= 0:
  309. data = self.data[self.listCtrl.GetItemData(pos)][2]
  310. canstart = (
  311. self.data[self.listCtrl.GetItemData(pos)][1]
  312. == win32service.SERVICE_STOPPED
  313. )
  314. else:
  315. data = 0
  316. canstart = 0
  317. self.GetDlgItem(self.IDC_START).EnableWindow(canstart)
  318. self.GetDlgItem(self.IDC_STOP).EnableWindow(
  319. data & win32service.SERVICE_ACCEPT_STOP
  320. )
  321. self.GetDlgItem(self.IDC_PAUSE).EnableWindow(
  322. data & win32service.SERVICE_ACCEPT_PAUSE_CONTINUE
  323. )
  324. self.GetDlgItem(self.IDC_CONTINUE).EnableWindow(
  325. data & win32service.SERVICE_ACCEPT_PAUSE_CONTINUE
  326. )
  327. def GetSelService(self):
  328. pos = self.listCtrl.GetCurSel()
  329. if pos < 0:
  330. return None
  331. pos = self.listCtrl.GetItemData(pos)
  332. return self.data[pos][-2:]
  333. def OnStartCmd(self, id, code):
  334. service = self.GetSelService()
  335. if not service:
  336. return
  337. s = win32service.OpenService(
  338. self.scm, service[1], win32service.SERVICE_ALL_ACCESS
  339. )
  340. win32service.StartService(s, None)
  341. win32service.CloseServiceHandle(s)
  342. self.ReloadData()
  343. def OnStopCmd(self, id, code):
  344. service = self.GetSelService()
  345. if not service:
  346. return
  347. s = win32service.OpenService(
  348. self.scm, service[1], win32service.SERVICE_ALL_ACCESS
  349. )
  350. win32service.ControlService(s, win32service.SERVICE_CONTROL_STOP)
  351. win32service.CloseServiceHandle(s)
  352. self.ReloadData()
  353. def OnPauseCmd(self, id, code):
  354. service = self.GetSelService()
  355. if not service:
  356. return
  357. s = win32service.OpenService(
  358. self.scm, service[1], win32service.SERVICE_ALL_ACCESS
  359. )
  360. win32service.ControlService(s, win32service.SERVICE_CONTROL_PAUSE)
  361. win32service.CloseServiceHandle(s)
  362. self.ReloadData()
  363. def OnContinueCmd(self, id, code):
  364. service = self.GetSelService()
  365. if not service:
  366. return
  367. s = win32service.OpenService(
  368. self.scm, service[1], win32service.SERVICE_ALL_ACCESS
  369. )
  370. win32service.ControlService(s, win32service.SERVICE_CONTROL_CONTINUE)
  371. win32service.CloseServiceHandle(s)
  372. self.ReloadData()
  373. def OnStartupCmd(self, id, code):
  374. service = self.GetSelService()
  375. if not service:
  376. return
  377. s = win32service.OpenService(
  378. self.scm, service[1], win32service.SERVICE_ALL_ACCESS
  379. )
  380. if StartupDlg(service[0], s).DoModal() == win32con.IDOK:
  381. self.ReloadData()
  382. def GetResource(self):
  383. style = (
  384. win32con.WS_POPUP
  385. | win32con.DS_SETFONT
  386. | win32con.WS_SYSMENU
  387. | win32con.WS_CAPTION
  388. | win32con.WS_VISIBLE
  389. | win32con.DS_MODALFRAME
  390. )
  391. exstyle = None
  392. t = [
  393. ["Services", (16, 16, 333, 157), style, exstyle, (8, "MS Shell Dlg")],
  394. ]
  395. t.append(
  396. [
  397. 130,
  398. "Ser&vice",
  399. -1,
  400. (6, 6, 70, 8),
  401. win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT,
  402. ]
  403. )
  404. t.append(
  405. [
  406. 130,
  407. "Status",
  408. -1,
  409. (164, 6, 42, 8),
  410. win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT,
  411. ]
  412. )
  413. t.append(
  414. [
  415. 130,
  416. "Startup",
  417. -1,
  418. (206, 6, 50, 8),
  419. win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT,
  420. ]
  421. )
  422. t.append(
  423. [
  424. 131,
  425. "",
  426. self.IDC_LIST,
  427. (6, 16, 255, 106),
  428. win32con.LBS_USETABSTOPS
  429. | win32con.LBS_SORT
  430. | win32con.LBS_NOINTEGRALHEIGHT
  431. | win32con.WS_BORDER
  432. | win32con.WS_CHILD
  433. | win32con.WS_VISIBLE
  434. | win32con.WS_TABSTOP
  435. | win32con.LBS_NOTIFY
  436. | win32con.WS_VSCROLL,
  437. ]
  438. )
  439. t.append(
  440. [
  441. 128,
  442. "Close",
  443. win32con.IDOK,
  444. (267, 6, 60, 14),
  445. win32con.WS_VISIBLE
  446. | win32con.WS_CHILD
  447. | win32con.WS_GROUP
  448. | win32con.WS_TABSTOP
  449. | win32con.BS_DEFPUSHBUTTON,
  450. ]
  451. )
  452. t.append(
  453. [
  454. 128,
  455. "&Start",
  456. self.IDC_START,
  457. (267, 27, 60, 14),
  458. win32con.WS_VISIBLE
  459. | win32con.WS_CHILD
  460. | win32con.WS_TABSTOP
  461. | win32con.BS_PUSHBUTTON,
  462. ]
  463. )
  464. t.append(
  465. [
  466. 128,
  467. "S&top",
  468. self.IDC_STOP,
  469. (267, 44, 60, 14),
  470. win32con.WS_VISIBLE
  471. | win32con.WS_CHILD
  472. | win32con.WS_TABSTOP
  473. | win32con.BS_PUSHBUTTON,
  474. ]
  475. )
  476. t.append(
  477. [
  478. 128,
  479. "&Pause",
  480. self.IDC_PAUSE,
  481. (267, 61, 60, 14),
  482. win32con.WS_VISIBLE
  483. | win32con.WS_CHILD
  484. | win32con.WS_TABSTOP
  485. | win32con.BS_PUSHBUTTON,
  486. ]
  487. )
  488. t.append(
  489. [
  490. 128,
  491. "&Continue",
  492. self.IDC_CONTINUE,
  493. (267, 78, 60, 14),
  494. win32con.WS_VISIBLE
  495. | win32con.WS_CHILD
  496. | win32con.WS_TABSTOP
  497. | win32con.BS_PUSHBUTTON,
  498. ]
  499. )
  500. t.append(
  501. [
  502. 128,
  503. "Sta&rtup...",
  504. self.IDC_STARTUP,
  505. (267, 99, 60, 14),
  506. win32con.WS_VISIBLE
  507. | win32con.WS_CHILD
  508. | win32con.WS_TABSTOP
  509. | win32con.BS_PUSHBUTTON,
  510. ]
  511. )
  512. t.append(
  513. [
  514. 128,
  515. "H&W Profiles...",
  516. self.IDC_PROFILES,
  517. (267, 116, 60, 14),
  518. win32con.WS_VISIBLE
  519. | win32con.WS_CHILD
  520. | win32con.WS_TABSTOP
  521. | win32con.BS_PUSHBUTTON,
  522. ]
  523. )
  524. t.append(
  525. [
  526. 128,
  527. "&Help",
  528. win32con.IDHELP,
  529. (267, 137, 60, 14),
  530. win32con.WS_VISIBLE
  531. | win32con.WS_CHILD
  532. | win32con.WS_TABSTOP
  533. | win32con.BS_PUSHBUTTON,
  534. ]
  535. )
  536. t.append(
  537. [
  538. 130,
  539. "St&artup Parameters:",
  540. -1,
  541. (6, 128, 70, 8),
  542. win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.SS_LEFT,
  543. ]
  544. )
  545. t.append(
  546. [
  547. 129,
  548. "",
  549. self.IDC_PARAMS,
  550. (6, 139, 247, 12),
  551. win32con.WS_VISIBLE
  552. | win32con.WS_CHILD
  553. | win32con.WS_GROUP
  554. | win32con.WS_BORDER
  555. | win32con.ES_AUTOHSCROLL,
  556. ]
  557. )
  558. return t
  559. if __name__ == "__main__":
  560. import sys
  561. machine = ""
  562. if len(sys.argv) > 1:
  563. machine = sys.argv[1]
  564. ServiceDlg(machine).DoModal()