qshinoの日記

Powershell関係と徒然なこと

python service on win32

概要

pywin32 を使用し、python でサービスを実装する。

不完全なベースクラスWsvcと、Wsvcを継承し機能を実装するサービスクラスSoneの2つを作成する。

サービスに関わる作業一覧

  • 準備 pip install pywin32
  • 登録 sone.py install
  • 更新 sone.py update
  • 停止 net stop Sone
  • GUI mmc Services.msc

サービス・クラス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()

ダーウイン

誤解

誤解と言われているもの。

“進化論を唱えたダーウィンは、「この世に生き残る生き物は、最も力の強いものか。そうではない。最も頭のいいものか。そうでもない。それは、変化に対応できる生き物だ」という考えを示したと言われています”

この出元

これは元々1960年代に米国の経営学者レオン・メギンソンがダーウィンの考えを独自に解釈して論文中に記した言葉であった。それを他者が引用を重ねるうち少しずつ変化して、最後にダーウィンの言葉として誤って伝えられるに至ったものである。

参照

https://gendai.ismedia.jp/articles/-/70729

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)