У меня есть три части кода, с которыми я работаю в данный момент:
- Закрытое исходное приложение (Main.exe)
- Объект VB с закрытым исходным кодом, реализованный как dll (comobj.dll)
- Код, который я разрабатываю в Python
comobj.dll содержит COM-объект (скажем, "MainInteract" ), который я хотел бы использовать с Python. Я уже могу использовать этот объект совершенно отлично от 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 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", но обычно в таких предложениях, как "Windows создаст контекст для вас, если вы укажете нужный материал в файлах .manifest". Я хотел бы, если это возможно, избегать файлов манифеста, поскольку один из них потребуется в той же папке, что и DLL COM-объекта (закрытый источник), и я бы предпочел не удалять файлы в этом каталоге, если я могу избежать этого.
Спасибо за помощь.