I'm trying to implement a COM server that will expose some methods, in order to link a third-party API with a PyQt application. The application is a grammar tool called Antidote. The server was registered successfully, but then I need to instantiate it and pass its object to Antidote's API. Thus;
Full code below;
def _connect(self):
self.server = win32com.client.Dispatch("Correcteur.Antidote") # , clsctx=pythoncom.CLSCTX_LOCAL_SERVER)
self.antidote = win32com.client.Dispatch("Antidote.ApiOle")
self.antidote.LanceOutilDispatch2(self.server, "C", "", "2.0") # Server, outil, langue, version APIIt successfully find the COM object in registry with the provided progid (Correcteur.Antidote), but it crash with a bunch of gibberish errors;Error:Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\user>"C:\Users\user\Desktop\AntidoteCOM.py - Shortcut.lnk"
pythoncom error: ERROR: server.policy could not create an instance.
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\server\policy.py", line 136, in CreateInstance
return retObj._CreateInstance_(clsid, reqIID)
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\server\policy.py", line 194, in _CreateInstance_
myob = call_func(classSpec)
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\server\policy.py", line 728, in call_func
return resolve_func(spec)(*args)
TypeError: __init__() missing 1 required positional argument: 'parent'
pythoncom error: Unexpected gateway error
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\server\policy.py", line 136, in CreateInstance
return retObj._CreateInstance_(clsid, reqIID)
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\server\policy.py", line 194, in _CreateInstance_
myob = call_func(classSpec)
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\server\policy.py", line 728, in call_func
return resolve_func(spec)(*args)
TypeError: __init__() missing 1 required positional argument: 'parent'
pythoncom error: CPyFactory::CreateInstance failed to create instance. (80004005)
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\client\dynamic.py", line 81, in _GetGoodDispatch
IDispatch = pythoncom.connect(IDispatch)
pywintypes.com_error: (-2147221021, 'Operation unavailable', None, None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "Z:\.antidote_\AntidoteCOM.py", line 44, in _connect
self.server = win32com.client.Dispatch("Correcteur.Antidote") # , clsctx=pythoncom.CLSCTX_LOCAL_SERVER)
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\client\dynamic.py", line 98, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\client\dynamic.py", line 83, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147467259, 'Unspecified error', None, None)From some examples I've seen, I tried to run the server beforehand in another thread, but the same error remains. def run(self):
pythoncom.CoInitialize()
localserver.serve(['{D390AE78-D6A2-47CF-B462-E4F2DC9C70F5}']) # ##I suppose something is wrong in my COM object class (AdapteurAntidote) ?Full code below;
#!/usr/bin/python3
import pythoncom
import winreg
import win32com.client
import win32com.server.register
from win32com.server import localserver
from pathlib import Path
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.body = QtWidgets.QTextEdit("Texte à corrigée.")
self.setCentralWidget(self.body)
self.antidote = ImplementationAntidote(self, self.body)
class ImplementationAntidote(QtCore.QObject):
def __init__(self, parent: QtCore.QObject, body: QtWidgets.QTextEdit):
super().__init__()
self.parent = parent
self.body = body
# self._register()
self._launch()
self.worker = WorkerThread()
self.workerThread = QtCore.QThread()
self.workerThread.started.connect(self.worker.run)
self.worker.moveToThread(self.workerThread)
self.workerThread.start()
QtCore.QTimer.singleShot(3000, self._connect)
@staticmethod
def hkey(path: str, name: str):
registry_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path, 0, winreg.KEY_READ)
value, regtype = winreg.QueryValueEx(registry_key, name)
winreg.CloseKey(registry_key)
return value
def _connect(self):
self.server = win32com.client.Dispatch("Correcteur.Antidote") # , clsctx=pythoncom.CLSCTX_LOCAL_SERVER) # ## Crash
self.antidote = win32com.client.Dispatch("Antidote.ApiOle")
self.antidote.LanceOutil2(self.server, "C", "", "2.0") # Server, outil, langue, version API
def _launch(self):
# antidoteAPI = self.hkey(r"Software\Druide informatique inc.\Antidote", "VersionAPI")
antidoteFolder = self.hkey(r"Software\Druide informatique inc.\Antidote", "DossierAntidote")
antidotePath = Path(antidoteFolder) / "Antidote.exe"
QtCore.QProcess.startDetached(str(antidotePath), ["-activex"])
def _register(self):
win32com.server.register.UseCommandLine(AdapteurAntidote)
class WorkerThread(QtCore.QObject):
def __init__(self):
super().__init__()
def run(self):
pythoncom.CoInitialize()
localserver.serve(['{D390AE78-D6A2-47CF-B462-E4F2DC9C70F5}']) # ##
class AdapteurAntidote:
_reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER # https://msdn.microsoft.com/en-us/library/windows/desktop/ms693716(v=vs.85).aspx
_reg_clsid_ = "{D390AE78-D6A2-47CF-B462-E4F2DC9C70F5}" # pythoncom.CreateGuid()
_reg_progid_ = "Correcteur.Antidote"
_public_methods_ = ["ActiveApplication", "ActiveDocument", "DonneDebutSelection", "DonneFinSelection",
"DonneIdDocumentCourant", "DonneIdZoneDeTexte", "DonneIdZoneDeTexteCourante", "DonneIntervalle",
"DonneLongueurZoneDeTexte", "DonneNbZonesDeTexte", "DonnePolice", "DonneTitreDocCourant",
"RemplaceIntervalle", "SelectionneIntervalle"]
_public_attrs_ = []
_reg_verprogid_ = "Correcteur.Antidote.1"
_reg_class_spec_ = "AntidoteCOM.AdapteurAntidote"
def __init__(self, parent):
super().__init__()
self.parent = parent
def DonneIdDocumentCourant(self):
raise NotImplementedError
def DonneIdZoneDeTexte(self):
raise NotImplementedError
def DonneIdZoneDeTexteCourante(self):
raise NotImplementedError
def DonneIntervalle(self):
raise NotImplementedError
def DonneLongueurZoneDeTexte(self):
raise NotImplementedError
def DonneNbZonesDeTexte(self):
raise NotImplementedError
def DonnePolice(self):
raise NotImplementedError
def DonneTitreDocCourant(self):
raise NotImplementedError
def RemplaceIntervalle(self):
raise NotImplementedError
def ActiveDocument(self):
self.parent.activeDocument()
def ActiveApplication(self):
self.parent.activeDocument()
def DonneDebutSelection(self) -> int:
return self.parent.donneDebutSelection()
def DonneFinSelection(self) -> int:
return self.parent.donneFinSelection()
def SelectionneIntervalle(self, debut: int, fin: int):
self.parent.selectionneIntervalle(debut, fin)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
gui = MainWindow()
gui.show()
app.exec()
