OLE automation

From Rosetta Code
Revision as of 01:28, 24 July 2011 by rosettacode>Tinku99 (ole automation ahk and python examples)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Task
OLE automation
You are encouraged to solve this task according to the task description, using any language you may know.

Provide an automation server implementing objects that can be accessed by a client running in a separate process. The client gets a proxy-object that can get and set properties as well as call methods on the object. The communication should be able to handle conversions of variants to and from the native value and array types.

AutoHotkey

Library: ComDispatch

by fincs: discussion

client: <lang autohotkey> ahk := comobjactive("ahkdemo.ahk") ahk.hello("hello world") </lang> server: <lang autohotkey>

  1. Persistent

CLSID_ThisScript := "{38A3EB13-D0C4-478b-9720-4D0B2D361DB9}" APPID_ThisScript := "ahkdemo.ahk" funcs := ["aRegisterIDs", "aGetObject", "aCallFunc", "hello"] server := ahkComServer(CLSID_ThisScript, APPID_ThisScript, funcs) return

aRegisterIDs(this, CLSID, APPID){ RegisterIDs(CLSID, APPID) }

hello(this, message){ msgbox % message } aGetObject(this, name){ global return %name% }

aCallFunc(this, func, args){ return %func%(args) }


F2:: py := ComObjActive("ahkdemo.python") py.write("hello") return


ahkcomserver()

ahkComServer(CLSID_ThisScript, APPID_ThisScript, funcs) { global serverReady server := object()

; CLSID_ThisScript := "{38A3EB13-D0C4-478b-9720-4D0B2D361DB9}"
; APPID_ThisScript := "Garglet.QueryServer"
 
 RegisterIDs(CLSID_ThisScript, APPID_ThisScript)

for i, func in funcs { str .= func . ", " } str := SubStr(str, 1, strlen(str) - 2)

 myObj := ComDispatch("", str)
Expose it
 if !(hRemote := ComRemote(myObj, CLSID_ThisScript))
 {
   MsgBox, 16, %A_ScriptName%, Can't remote the object!
   ExitApp
 }

server.CLSID := CLSID_ThisScript server.APPID := APPID_ThisScript server.hRemote := hRemote serverReady := 1

 return server

}

  1. Include ComRemote.ahk
  2. include lib\ComDispTable.ahk
  3. include lib\ComDispatch.ahk
  4. include lib\ComVar.ahk

</lang>

Python

server uses a client of the ahk server above to register the clsid in the windows registry. <lang python>#!/usr/bin/env python

  1. -*- coding: utf-8 -*-

import win32com.client from win32com.server.util import wrap, unwrap from win32com.server.dispatcher import DefaultDebugDispatcher from ctypes import * import commands import pythoncom import winerror from win32com.server.exception import Exception

clsid = "{55C2F76F-5136-4614-A397-12214CC011E5}" iid = pythoncom.MakeIID(clsid) appid = "python.client"

class VeryPermissive:

   def __init__(self):
       self.data = []
       self.handle = 0
       self.dobjects = {}        
   def __del__(self):
       pythoncom.RevokeActiveObject(self.handle)
   def _dynamic_(self, name, lcid, wFlags, args):
       if wFlags & pythoncom.DISPATCH_METHOD:
           return getattr(self,name)(*args)
       if wFlags & pythoncom.DISPATCH_PROPERTYGET:
           try:
               # to avoid problems with byref param handling, tuple results are converted to lists.
               ret = self.__dict__[name]
               if type(ret)==type(()):
                   ret = list(ret)
               return ret
           except KeyError: # Probably a method request.
               raise Exception(scode=winerror.DISP_E_MEMBERNOTFOUND)
       if wFlags & (pythoncom.DISPATCH_PROPERTYPUT | pythoncom.DISPATCH_PROPERTYPUTREF):
           setattr(self, name, args[0])
           return
       raise Exception(scode=winerror.E_INVALIDARG, desc="invalid wFlags")
   def write(self, x):
       print x
       return 0

import win32com.server.util, win32com.server.policy child = VeryPermissive() ob = win32com.server.util.wrap(child, usePolicy=win32com.server.policy.DynamicPolicy) try:

   handle = pythoncom.RegisterActiveObject(ob, iid, 0)

except pythoncom.com_error, details:

   print "Warning - could not register the object in the ROT:", details
   handle = None    

child.handle = handle

ahk = win32com.client.Dispatch("ahkdemo.ahk") ahk.aRegisterIDs(clsid, appid)

  1. autohotkey.exe ahkside.ahk
  2. python /c/Python26/Scripts/ipython.py -wthread -i pythonside.py
  3. must use -wthread otherwise calling com client hangs

</lang> client<lang Python> client = win32com.client.Dispatch("python.client") client.write("hello world") </lang