OLE automation: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 78: Line 78:
requires [http://sourceforge.net/projects/pywin32/ pywin32].
requires [http://sourceforge.net/projects/pywin32/ pywin32].
server uses a client of the ahk server above to register the clsid in the windows registry.
server uses a client of the ahk server above to register the clsid in the windows registry.
translated from win32com/test/testDynamic.py
<lang python>#!/usr/bin/env python
<lang python>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-

Revision as of 17:23, 24 July 2011

Task
OLE automation
You are encouraged to solve this task according to the task description, using any language you may know.

OLE Automation is an inter-process communication mechanism based on Component Object Model (COM) on Microsoft Windows.

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 call methods on the object. The communication should be able to handle conversions of variants to and from the native value types.

AutoHotkey

Library: ComDispatch

by fincs:discussion

client: using the ahk ole server as well as the python ole server implemented below<lang autohotkey> ahk := comobjactive("ahkdemo.ahk") ahk.hello("hello world") py := ComObjActive("ahkdemo.python") py.write("hello") return </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) }

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

requires pywin32. server uses a client of the ahk server above to register the clsid in the windows registry. translated from win32com/test/testDynamic.py <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> import win32com.client client = win32com.client.Dispatch("python.client") client.write("hello world") </lang>