.NET Core 6.0 COM 与 Python/Octave 的互操作性问题

.NET Core 6.0 COM interoperability issues with Python/Octave

我目前正在尝试在 .NET Core 6 中创建一个 COM 对象。为此,我创建了一个 class 库并像这样编辑项目:

C#:

项目文件 (*.csproj):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <EnableComHosting>true</EnableComHosting>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>
    
</Project>

COM 对象 (*.cs):

using System;
using System.Runtime.InteropServices;

namespace COMNetCore6
{
    [ComVisible(true)]
    [Guid("64D6F9F6-6163-401A-82E6-C941CAF01399")]
    [ProgId("HelloWorldCOMObject")]
    public class ComObject
    {
        public string SayHello() => "Hello world from .NET Core";
    }
}

构建项目后,我得到一个 *.comhost.dll 文件,我可以使用命令 'regsvr32 *.comhost.dll' 将其添加到注册表中。 comhost.dll 注册成功 并且 它按预期在 Excel 中为 Visual Basic 工作

当我尝试在另一种编程语言中使用此 COM 对象时,它不起作用。我试过使用 Octave 和 Python。虽然 Octave 只告诉我它无法创建服务器,但 Python 至少给我这个错误:

Python:

>>> import win32com.client
>>> comobj = win32com.client.Dispatch("HelloWorldCOMObject")
Traceback (most recent call last):
  File "C:\*\AppData\Local\Programs\Python\Python39-32\lib\site-packages\win32com\client\dynamic.py", line 86, 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 "<stdin>", line 1, in <module>
  File "C:\*\AppData\Local\Programs\Python\Python39-32\lib\site-packages\win32com\client\__init__.py", line 117, in Dispatch
    dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch, userName, clsctx)
  File "C:\*\AppData\Local\Programs\Python\Python39-32\lib\site-packages\win32com\client\dynamic.py", line 106, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "C:\*\AppData\Local\Programs\Python\Python39-32\lib\site-packages\win32com\client\dynamic.py", line 88, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(
pywintypes.com_error: (-2147467262, 'No such interface supported', None, None)

我已尝试按照这些链接中描述的步骤(尤其是第一个)并根据我的需要调整它们来解决此问题:

https://github.com/GregReddick/ComTestLibrary/tree/master/ComTestLibrary1 https://docs.microsoft.com/en-us/dotnet/core/native-interop/expose-components-to-com

不幸的是 none 我试过的方法奏效了。我试图为 COM 对象创建一个接口并在 C# 中使用正确的互操作性注释,但错误仍然存​​在。正如我所说的,没有界面且几乎没有任何来自上面的注释的基本方法适用于 Visual Basic。

在这种情况下,我尝试使用没有 TLB(类型库)的后期绑定,因为我需要它同时适用于后期绑定(没有 TLB)和早期绑定(有 TLB),我决定从后期开始绑定。

有一个关于延迟绑定方法的类似问题,目前还没有回答:'No such interface supported' when using .NET 6.0 COM object in python 3.9

由于 COM 对象适用于 Visual Basic,但不适用于其他编程语言,我不确定究竟是什么导致了这个问题。

.NET Core 包装器不支持您在创建 COM 对象的同时请求 IDispatch 的此类调用:

C/C++:

IDispatch* disp;
CoCreateInstance(YourCLSID, NULL, CLSCTX_ALL, IID_IDispatch, &disp); // fails

Python:

disp = pythoncom.CoCreateInstance(YourCLSID, None, pythoncom.CLSCTX_ALL, pythoncom.IID_IDispatch) // fails

您必须首先获得 IUnknown 引用和 IDispatch 的 QI,就像 python 中的这样(Excel/VBA 所做的):

import pythoncom
import pywintypes
from win32com.client import Dispatch

unk = pythoncom.CoCreateInstance(pywintypes.IID('{64D6F9F6-6163-401A-82E6-C941CAF01399}'), None, pythoncom.CLSCTX_ALL, pythoncom.IID_IUnknown)
disp = Dispatch(unk.QueryInterface(pythoncom.IID_IDispatch))
print disp.SayHello

恕我直言,python 应该修改 COM 支持以始终执行此操作...