3

I am trying to load a windows COM DLL in Python to get all the exposed interfaces.

Using the dependency walker tool I can list the functions in the dll. I see only 4 functions:

  1. DllCanUnloadNow
  2. DllGetClassObject
  3. DllRegisterServer
  4. DllUnregisterServer

If I understood correctly, I need to get an object of the class using DllGetClassObject() and then use the exposed interfaces.

I am using pythoncom and win32com.client to extract the object (got the recipe from another stackoverflow post)

import pythoncom
import win32com.client

def CreateInstanceFromDll(dll, clsid_class, iid_interface=pythoncom.IID_IDispatch, pUnkOuter=None, dwClsContext=pythoncom.CLSCTX_SERVER):
    from uuid import UUID
    from ctypes import OleDLL, c_long, byref

    e = OleDLL(dll)
    print (e)
    #print (e.DllRegisterServer())

    clsid_class = UUID(clsid_class).bytes_le
    iclassfactory = UUID(str(pythoncom.IID_IClassFactory)).bytes_le
    com_classfactory = c_long(0)
    hr = e.DllGetClassObject(clsid_class, iclassfactory, byref(com_classfactory))
    MyFactory = pythoncom.ObjectFromAddress(com_classfactory.value, pythoncom.IID_IClassFactory)
    i = MyFactory.CreateInstance(pUnkOuter, iid_interface)
    d = win32com.client.__WrapDispatch(i)
    return d

print (CreateInstanceFromDll('PTSControl.dll', '{32a917e0-b1d4-4692-b0d7-793d81d9c8b5}'))

I got the cls_id from the windows registry for the PTSControl tool. But this throws an WindowsError.

<OleDLL 'PTSControl.dll', handle 70010000 at 2451470>
Traceback (most recent call last):
  File "C:\wp\automation.py", line 35, i
n <module>
    print (CreateInstanceFromDll('PTSControl.dll', '{32a917e0-b1d4-4692-b0d7-793
d81d9c8b5}'))
  File "C:\wp\automation.py", line 29, i
n CreateInstanceFromDll
    hr = e.DllGetClassObject(clsid_class, iclassfactory, byref(com_classfactory)
)
  File "_ctypes/callproc.c", line 945, in GetResult
WindowsError: [Error -2147467262] No such interface supported

Any ideas what I am doing wrong? I do not have access to the tool's source code.

In C++ this is 2-step process but no idea how to do it in Python:

  1. CoInitializeEx()
  2. CoCreateInstance()

In general, what is the best technique to access a Windows COM DLL in python? Thanks !!

Hiadore
  • 686
  • 3
  • 15
sk11
  • 1,779
  • 1
  • 17
  • 29
  • You only need to follow the example in the post you linked if the DLL isn't registered. Since it must be registers for `CoCreateInstance` to work in C++ you don't need to go to such extremes. `win32com` should support `CoCreateInstance` or something to the same effect. – Ross Ridge Aug 11 '14 at 20:27

1 Answers1

1

I couldn't figure out how to call DllGetClassObject directly, but the following approach worked for me. And it should do for you too, seeing as your DLL has DllRegisterServer and DllUnregisterServer:

cd c:\path\to\libs
regsvr32 YourLib.dll

And then in Python:

import win32com.client
lib = win32com.client.Dispatch("Some.Thing")
lib.SomeFunction()

I am not sure what you should specify as parameter for Dispatch. My DLL came with a sample VB app that did this:

Dim lib As New Some.Thing
lib.SomeFunction()
mozey
  • 2,222
  • 2
  • 27
  • 34
  • Thanks for the input. With your input atleast I was able to open the application but then immediately after opening the application my python script crashes with following error - `pywintypes.com_error: (-2147467262, 'No such interface supported', None, None)` Any ideas there ? – sk11 Aug 26 '14 at 13:02