我目前正在使用三段代码:
- 闭源应用程序 (Main.exe)
- 实现为 dll (comobj.dll) 的闭源 VB COM 对象
- 我正在用 Python 开发的代码
comobj.dll 托管一个我想从 Python 中使用的 COM 对象(可以说是“MainInteract”)。我已经可以从 IronPython 完美地使用这个对象,但由于其他要求,我需要从常规 Python 使用它。我相信这里最好的方法是使用 win32com,但我根本无法取得任何进展。
首先,一些可用的 IronPython 代码:
import clr
import os
import sys
__dir__ = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, __dir__)
sys.path.append(r"C:\Path\To\comobj.dll") #This is where the com object dll actually is
clr.AddReferenceToFileAndPath(os.path.join(__dir__, r'comobj_1_1.dll')) #This is the .NET interop assembly that was created automatically via SharpDevelop's COM Inspector
from comobj_1_1 import clsMainInteract
o = clsMainInteract()
o.DoStuff(True)
现在我在常规 Python 中尝试的代码:
>>> import win32com.client
>>> win32com.client.Dispatch("{11111111-comobj_guid_i_got_from_com_inspector}")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python26\lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "C:\Python26\lib\site-packages\win32com\client\dynamic.py", line 104, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "C:\Python26\lib\site-packages\win32com\client\dynamic.py", line 84, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147221164, 'Class not registered', None, None)
我还尝试使用 TLB 的友好名称:
>>> import win32com.client
>>> win32com.client.Dispatch("Friendly TLB Name I Saw")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python26\lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "C:\Python26\lib\site-packages\win32com\client\dynamic.py", line 104, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "C:\Python26\lib\site-packages\win32com\client\dynamic.py", line 84, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147221005, 'Invalid class string', None, None)
事实上,我唯一的成功是:
import pythoncom
tlb = pythoncom.LoadRegTypeLib("{11111111-comobj_guid_i_got_from_com_inspector}",1,1,0)
>>> tlb
<PyITypeLib at 0x00AD7D78 with obj at 0x0025EDF0>
>>> tlb.GetDocumentation(1)
(u'clsMainInteract', None, 0, None)
但我不知道如何从那里得到一个对象。我认为我的问题是我需要将 dll 加载到我的进程中并让它在我的进程的 COM 源中注册自己,这样我就可以正确地 CoCreateInstance / win32com.client.Dispatch() 就可以了。
我还看到了引用的激活上下文,尤其是在谈论“无注册 COM”时,但通常在诸如“如果您在 .manifest 文件中指定正确的内容,Windows 将为您创建一个上下文”之类的句子中。如果可能的话,我想避免使用清单文件,因为在与(封闭源代码)COM 对象 dll 相同的文件夹中需要一个文件,如果可以避免的话,我宁愿不要在该目录中删除任何文件。
谢谢您的帮助。