python service on win32
概要
pywin32 を使用し、python でサービスを実装する。
不完全なベースクラスWsvcと、Wsvcを継承し機能を実装するサービスクラスSoneの2つを作成する。
サービスに関わる作業一覧
サービス・クラスSone
#!/usr/bin/python3 # # sone.py # from time import sleep from wsvc import Wsvc import logging logging.basicConfig( filename = 'c:\\sone.log', level = logging.DEBUG, format = '[service-one] %(levelname)-7.7s %(message)s') class Sone(Wsvc): _svc_name_ = "Sone" _svc_display_name_ = "Service 1" _svc_description_ = "Enjoy!" def start(self): self.isrunning = True def stop(self): self.isrunning = False def main(self): while self.isrunning: logging.info('sone main.') sleep(5) if __name__ == '__main__': Sone.parse_command_line()
ベース・クラスWsvc
#!/usr/bin/python3 # # wsvc.py # import socket import win32serviceutil import servicemanager import win32event import win32service class Wsvc(win32serviceutil.ServiceFramework): '''Base class to create winservice in Python''' _svc_name_ = 'pythonService' _svc_display_name_ = 'Python Service' _svc_description_ = 'Python Service Description' @classmethod def parse_command_line(cls): ''' ClassMethod to parse the command line ''' win32serviceutil.HandleCommandLine(cls) def __init__(self, args): ''' Constructor of the winservice ''' win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) socket.setdefaulttimeout(60) def SvcStop(self): ''' Called when the service is asked to stop ''' self.stop() self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) def SvcDoRun(self): ''' Called when the service is asked to start ''' self.start() servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, '')) self.main() def start(self): ''' Override to add logic before the start eg. running condition ''' pass def stop(self): ''' Override to add logic before the stop eg. invalidating running condition ''' pass def main(self): ''' Main class to be ovverridden to add logic ''' pass # entry point of the module: copy and paste into the new module # ensuring you are calling the "parse_command_line" of the new created class if __name__ == '__main__': Wsvc.parse_command_line()
GetAsyncKeyStatus()
GetAsyncKeyStatus()
SHORT GetAsyncKeyStatus( int vkey )
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate
return value
msb : 1 down 0 up
lsb : 1 changed from last call
VKEY
VK_MENU 0x12
https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
Python ctypes POINTER() pointer() byref()
違い
- POINTER( ctypes型 ) ポインタ型を返す
- pointer( ctypes instance ) ポインタインスタンスを生成。参照渡しにも利用可能だが、重い処理。
- bytef( ctypes instance ) パラメータの参照渡し用の軽い処理。参照渡し用のポインタを返す。
例
from ctypes import * pclass = POINTER(c_int) p = pclass(c_int(24)) p.contents = c_int(12) a = c_int(35) b = pointer(a) print( a.value ) # 35 c = c_int(40) windll.user32.poi( byref(a), pointer(c) ) # それぞれ3, 4がセットされる。 # 参照渡し使用時は機能は同等 print( a.value, c.value ) # 3 4
関数ファクトリ
ia = (c_int * 5 )(5,3,7,99,1) qsort = libc.qsort qsort.restype = None @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int)) def py_cmp_func(a, b): print("py_cmp_func", a[0], b[0]) return a[0] - b[0] qsort(ia, len(ia), sizeof(c_int), py_cmp_func) # py_cmp_func 5 1 # py_cmp_func 33 99 # py_cmp_func 7 33 # py_cmp_func 1 7 # py_cmp_func 5 7
python ctypes フォアグラウンド・ウインドウの操作
python ctypes win
cのdllをpythonから呼び出せる。cdllがデフォルトで定義されている。libc=cdll.msvcrt , libc=CDLL('lbc.so.6')等でインスタンス生成
winの場合は、windll, oledllも追加で定義される。
kernel32, user32。64bitでもファイル名が32なのは気になる。
コード
from ctypes import * user32 = windll.user32 # get screen resolution of primary monitor res = (user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)) # res is (2293, 960) for 3440x1440 display at 150% scaling user32.SetProcessDPIAware() res = (user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)) # res is now (3440, 1440) for 3440x1440 display at 150% scaling # get handle for Notepad window # non-zero value for handle should mean it found a window that matches handle = user32.FindWindowW(u'Notepad', None) # or # handle = user32.FindWindowW(None, u'Untitled - Notepad') # meaning of 2nd parameter defined here # https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx # minimize window using handle user32.ShowWindow(handle, 6) # maximize window using handle user32.ShowWindow(handle, 9) # move window using handle # MoveWindow(handle, x, y, height, width, repaint(bool)) user32.MoveWindow(handle, 100, 100, 400, 400, True)