如何在Python中正确加载Windows COM DLL

3 投票
1 回答
6256 浏览
提问于 2025-04-18 11:18

我正在尝试在Python中加载一个Windows的COM DLL,以获取所有可用的接口。

我使用了一个叫做依赖查看器的工具,能够列出这个DLL中的函数。我只看到4个函数:

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

如果我理解得没错,我需要通过DllGetClassObject()来获取一个类的对象,然后使用那些可用的接口。

我正在使用pythoncom和win32com.client来提取这个对象(这个方法是从另一个stackoverflow帖子上找到的)

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}'))

我从Windows注册表中得到了PTSControl工具的cls_id。但是这引发了一个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

有没有人知道我哪里做错了?我没有这个工具的源代码。

在C++中这是一个两步的过程,但我不知道在Python中该怎么做:

  1. CoInitializeEx()
  2. CoCreateInstance()

总的来说,使用Python访问Windows COM DLL的最佳方法是什么?谢谢!!

1 个回答

1

我不知道怎么直接调用 DllGetClassObject,但我找到了一种方法可以解决这个问题。这种方法对我有效,对你也应该有效,因为你的 DLL 有 DllRegisterServer 和 DllUnregisterServer:

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

然后在 Python 中:

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

我不太确定你应该为 Dispatch 指定什么参数。我的 DLL 附带了一个示例 VB 应用程序,它是这样做的:

Dim lib As New Some.Thing
lib.SomeFunction()

撰写回答