PDICの機能を利用するPythonスクリプト
DDEを使ってPDICを操作するPythonスクリプトを作ってみた。要 Python Win32 Extensions。
なんかもう、Win32にべったりでアレな感じなんだけども。
pdictool search word
で PDIC を Foreground にして word を入力した状態に。
pdictool popup word
でポップアップ検索ができる。
py2exeでWindows用のバイナリ*1を作っておいたので、こんなのでも欲しい人はご自由に。
しかし、PDIC の DDE はパラメータを Null Terminate しておかないといけないのな。ついでに戻り値も Null Terminate されているんだけど。小一時間ハマってしまったよ。
import sys import win32ui, dde import win32con, win32process, win32gui, win32event import pywintypes import _winreg VERSION = "0.1" DEFAULT_DDE_SERVICE_NAME = "PDICW" DDE_CLIENT_NAME = "PDICClient" REG_PATH = "SOFTWARE\\ReliefOffice\\CurrentVersion\\App Paths\\PDICW32.EXE" EXEC_WAIT_TIME = 500 _SERVER = None class PDICError(Exception): def __init__(self, message): self.message = message def __str__(self): return str(self.message) class PDIC: def __init__(self, service=DEFAULT_DDE_SERVICE_NAME, topic = "PDIC"): global _SERVER if _SERVER is None: _SERVER = dde.CreateServer() _SERVER.Create(DDE_CLIENT_NAME) self.conversation = dde.CreateConversation(_SERVER) try: self.conversation.ConnectTo(service, topic) except: if sys.exc_info()[0] != 'error': raise self._exec_pdic(service) self.conversation.ConnectTo(service, topic) def Request(self, name): return self.conversation.Request(name)[:-1] def Poke(self, name, param): self.conversation.Poke(name, param + "\x00") def Exec(self, name): self.conversation.Exec(name) def _exec_pdic(self, service, wait = EXEC_WAIT_TIME): cmd = self._get_pdic_path() si = win32process.STARTUPINFO() si.dwFlags = win32con.STARTF_USESHOWWINDOW si.wShowWindow = win32con.SW_SHOWNOACTIVATE | win32con.SW_MINIMIZE cmdline = cmd + " -e " + shell_escape(service) try: handles = win32process.CreateProcess( None, cmdline, None, None, 1, win32process.CREATE_NEW_CONSOLE, None, None, si) except pywintypes.error: raise PDICError("Cannot execute " + cmd) if handles and wait != 0: win32event.WaitForInputIdle(handles[0], wait) if handles: return True else: return False def _get_pdic_path(self): try: key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, REG_PATH) except WindowsError: raise PDICError("PDIC not found") else: val = _winreg.QueryValue(key, "") key.Close() return val def shell_escape(str): replaces = ('"', "'", ' ') for replace in replaces: str = str.replace(replace, '\\' + replace) return str def focus(): pdic = PDIC(topic = "PDIC") handle = int(pdic.Request("GetMainWindow")) win32gui.SetForegroundWindow(handle) win32gui.ShowWindow(handle, win32con.SW_RESTORE) def main(): from optparse import OptionParser commands = ["popup", "search"] def popup(word, options): dict = PDIC(service = options.service_name, topic = "Dictionary") dict.Poke("Open", "") dict.Poke("PopupSearch", word) def search(word, options): simulate = PDIC(service = options.service_name, topic = "Simulate") simulate.Poke("InputWord", word) focus() usage = "usage: %%prog [options] (%s) word" % "|".join(commands) parser = OptionParser(usage = usage, version = VERSION) parser.add_option("-s", "--service", dest="service_name", help="DDE service name", metavar="service", default=DEFAULT_DDE_SERVICE_NAME) (options, args) = parser.parse_args() if len(args) < 2: parser.print_help() sys.exit(1) command = args[0] if command not in commands: parser.print_help() sys.exit(1) word = " ".join(args[1:]) eval(command)(word, options) if __name__ == '__main__': try: main() except PDICError, error: print >>sys.stderr, error