Python 中的 COM 事件和在 .NET Core 6.0 中创建的 COM 对象的互操作性问题
Interoperability issue with COM events in Python and a COM object created in .NET Core 6.0
我目前正在尝试创建一个在 .NET Core 6.0 中用 C# 制作的 COM 对象。 COM 对象本身按预期工作。我遇到的问题与 COM 对象包含的自定义事件有关。我已经作为客户端测试了 Excel 并且事件会正常工作。当我尝试使用 COM 对象及其在 Python 中的事件时,尽管它不起作用。
我这样试过:
import win32com
from win32com.client import DispatchWithEvents
import pythoncom
import pywintypes
class ComEvents():
def OnAdditionDone():
print('Addition is done.')
unk = pythoncom.CoCreateInstance(pywintypes.IID('ComplexComObject'), None, pythoncom.CLSCTX_ALL, pythoncom.IID_IUnknown)
dispevents = DispatchWithEvents(unk.QueryInterface(pythoncom.IID_IDispatch), ComEvents)
我收到以下错误消息:
Message=This COM object can not automate the makepy process - please run makepy manually for this object
Source=C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py
StackTrace:
During handling of the above exception, another exception occurred:
File "C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py", line 13, in <module> (Current frame)
dispevents = DispatchWithEvents(unk.QueryInterface(pythoncom.IID_IDispatch), ComEvents)
我不确定是否正在尝试正确访问 python 中的 COM 事件。
我也试过这样做:
import win32com.client
from win32com.client import Dispatch
import pythoncom
import pywintypes
EventListener = win32com.client.getevents('ComplexComObject')
class Events(EventListener):
def OnAdditionDone():
print('Addition is done.')
unk = pythoncom.CoCreateInstance(pywintypes.IID('ComplexComObject'), None, pythoncom.CLSCTX_ALL, pythoncom.IID_IUnknown)
dispevents = Dispatch(unk.QueryInterface(pythoncom.IID_IDispatch))
导致此错误的原因:
Message=NoneType takes no arguments
Source=C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py
StackTrace:
File "C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py", line 9, in <module> (Current frame)
class Events(EventListener):
我不确定我做错了什么,或者是否有更好的方法来使用 python 中的 COM 事件。由于我对 Python 不是很精通,这两种方法是我唯一能找到的方法,但都不适合我。
我不确定我的 C# 代码是否存在问题,因为事件确实适用于 Excel。
可以在这个 GitHub 存储库中找到 C# COM 对象代码:https://github.com/Spikxzy/ComInDotNETCore
如果您想自己测试代码,请务必正确编辑 ComObjectWithEvents.csproj 中的以下标记:
<PropertyGroup>
<!--
Change the following tags so that this path 'C:$(VSLocation)\Microsoft Visual Studio$(VSVersion)\VC\Tools\MSVC$(CLVersion)\bin\Hostx64\x64'
is valid for your Visual Studio installation (the path should lead to a cl.exe).
-->
<VSVersion>2022\Professional</VSVersion>
<VSLocation>Program Files</VSLocation>
<CLVersion>14.31.31103</CLVersion>
<DriveLetter>N:</DriveLetter>
<KitsVersion>10.0.19041.0</KitsVersion>
</PropertyGroup>
构建项目后,请务必在命令行工具中使用 'regsvr32' 注册生成的“*.comhost.dll”文件。
这是正确的 python 代码:
import win32com.client
from win32com.client import Dispatch
import pythoncom
import pywintypes
unk = pythoncom.CoCreateInstance(pywintypes.IID('ComplexComObject'), None, pythoncom.CLSCTX_ALL, pythoncom.IID_IUnknown)
dispevents = Dispatch(unk.QueryInterface(pythoncom.IID_IDispatch))
class MyEvents:
def OnAdditionDone(self):
print('Addition is done.')
EventListener = win32com.client.WithEvents(dispevents, MyEvents)
print(dispevents.Addition(123, 456))
但它不会按原样工作。
首先要做的是确保您准备的类型库 (.tlb) 已注册。在 ComObjectWithEvents 项目中不是这种情况,但您可以借用和改编您在 ComObjectWithTLBRegistration 项目中已有的代码。
如果您不这样做,您将得到 ti = disp._oleobj_.GetTypeInfo() pywintypes.com_error: (-2146234011, 'OLE error 0x80131165', None, None)
,即 TLBX_W_LIBNOTREGISTERED。
之后你会得到另一个错误:Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
错误。这是因为您的调度接口在 C# 中定义不正确,目前是:
[ComVisible(true)]
[Guid(AssemblyInfo.ComEventsGuid)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)] // not good
public interface ComEvents
{
[DispId(1)]
void OnAdditionDone();
}
而它必须是这样的:
[ComVisible(true)]
[Guid(AssemblyInfo.ComEventsGuid)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ComEvents
{
[DispId(1)]
void OnAdditionDone();
}
我目前正在尝试创建一个在 .NET Core 6.0 中用 C# 制作的 COM 对象。 COM 对象本身按预期工作。我遇到的问题与 COM 对象包含的自定义事件有关。我已经作为客户端测试了 Excel 并且事件会正常工作。当我尝试使用 COM 对象及其在 Python 中的事件时,尽管它不起作用。
我这样试过:
import win32com
from win32com.client import DispatchWithEvents
import pythoncom
import pywintypes
class ComEvents():
def OnAdditionDone():
print('Addition is done.')
unk = pythoncom.CoCreateInstance(pywintypes.IID('ComplexComObject'), None, pythoncom.CLSCTX_ALL, pythoncom.IID_IUnknown)
dispevents = DispatchWithEvents(unk.QueryInterface(pythoncom.IID_IDispatch), ComEvents)
我收到以下错误消息:
Message=This COM object can not automate the makepy process - please run makepy manually for this object
Source=C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py
StackTrace:
During handling of the above exception, another exception occurred:
File "C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py", line 13, in <module> (Current frame)
dispevents = DispatchWithEvents(unk.QueryInterface(pythoncom.IID_IDispatch), ComEvents)
我不确定是否正在尝试正确访问 python 中的 COM 事件。
我也试过这样做:
import win32com.client
from win32com.client import Dispatch
import pythoncom
import pywintypes
EventListener = win32com.client.getevents('ComplexComObject')
class Events(EventListener):
def OnAdditionDone():
print('Addition is done.')
unk = pythoncom.CoCreateInstance(pywintypes.IID('ComplexComObject'), None, pythoncom.CLSCTX_ALL, pythoncom.IID_IUnknown)
dispevents = Dispatch(unk.QueryInterface(pythoncom.IID_IDispatch))
导致此错误的原因:
Message=NoneType takes no arguments
Source=C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py
StackTrace:
File "C:\PathToProject\PythonEventTesting\PythonEventTesting\PythonEventTesting.py", line 9, in <module> (Current frame)
class Events(EventListener):
我不确定我做错了什么,或者是否有更好的方法来使用 python 中的 COM 事件。由于我对 Python 不是很精通,这两种方法是我唯一能找到的方法,但都不适合我。
我不确定我的 C# 代码是否存在问题,因为事件确实适用于 Excel。
可以在这个 GitHub 存储库中找到 C# COM 对象代码:https://github.com/Spikxzy/ComInDotNETCore
如果您想自己测试代码,请务必正确编辑 ComObjectWithEvents.csproj 中的以下标记:
<PropertyGroup>
<!--
Change the following tags so that this path 'C:$(VSLocation)\Microsoft Visual Studio$(VSVersion)\VC\Tools\MSVC$(CLVersion)\bin\Hostx64\x64'
is valid for your Visual Studio installation (the path should lead to a cl.exe).
-->
<VSVersion>2022\Professional</VSVersion>
<VSLocation>Program Files</VSLocation>
<CLVersion>14.31.31103</CLVersion>
<DriveLetter>N:</DriveLetter>
<KitsVersion>10.0.19041.0</KitsVersion>
</PropertyGroup>
构建项目后,请务必在命令行工具中使用 'regsvr32' 注册生成的“*.comhost.dll”文件。
这是正确的 python 代码:
import win32com.client
from win32com.client import Dispatch
import pythoncom
import pywintypes
unk = pythoncom.CoCreateInstance(pywintypes.IID('ComplexComObject'), None, pythoncom.CLSCTX_ALL, pythoncom.IID_IUnknown)
dispevents = Dispatch(unk.QueryInterface(pythoncom.IID_IDispatch))
class MyEvents:
def OnAdditionDone(self):
print('Addition is done.')
EventListener = win32com.client.WithEvents(dispevents, MyEvents)
print(dispevents.Addition(123, 456))
但它不会按原样工作。
首先要做的是确保您准备的类型库 (.tlb) 已注册。在 ComObjectWithEvents 项目中不是这种情况,但您可以借用和改编您在 ComObjectWithTLBRegistration 项目中已有的代码。
如果您不这样做,您将得到 ti = disp._oleobj_.GetTypeInfo() pywintypes.com_error: (-2146234011, 'OLE error 0x80131165', None, None)
,即 TLBX_W_LIBNOTREGISTERED。
之后你会得到另一个错误:Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
错误。这是因为您的调度接口在 C# 中定义不正确,目前是:
[ComVisible(true)]
[Guid(AssemblyInfo.ComEventsGuid)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)] // not good
public interface ComEvents
{
[DispId(1)]
void OnAdditionDone();
}
而它必须是这样的:
[ComVisible(true)]
[Guid(AssemblyInfo.ComEventsGuid)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ComEvents
{
[DispId(1)]
void OnAdditionDone();
}