I am currently trying to create a COM object in .NET Core 6. To achieve this I have made a class library and edited the project like this:
C#:
Project file (*.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 object (*.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";
}
}
After building the project I get a *.comhost.dll file which I can add to the registry by using the command 'regsvr32 *.comhost.dll'. The comhost.dll gets registered successfully and it is working for Visual Basic in Excel as intended.
When I try using this COM object in another programming language though it will not work. I have tried using Octave and Python. While Octave only tells me that it wasn't able to create a server, Python gives me this error at least:
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)
I have tried to solve this problem by following the steps described in these links (especially the first one) and adapting them to what I needed:
Can I connect a .NET 5 COM interop object with VB6? https://github.com/GregReddick/ComTestLibrary/tree/master/ComTestLibrary1 https://learn.microsoft.com/en-us/dotnet/core/native-interop/expose-components-to-com
Unfortunately none of the approaches I tried worked. I have tried to create an interface for the COM object and use the correct interoperability annotations in C# but the error was still there. As I have said though the basic approach with no interface and barely any annotation from above worked for Visual Basic.
In this case I am trying to use late binding without a TLB (type library) because I need this to work for both late binding (without TLB) and early binding (with TLB) and I decided to start with late binding.
There has been a similar question regarding the late binding approach which wasn't answered as of now: 'No such interface supported' when using .NET 6.0 COM object in python 3.9.
Since the COM object works fine for Visual Basic but doesn't work for other programming languages I am not sure what exactly causes this issue.
The .NET Core wrapper doesn't support this type of call where you ask for IDispatch at the same time you create the COM object:
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
You must first get an IUnknown reference and QI for IDispatch on it, like this in python (which is what Excel/VBA does):
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
IMHO, python COM support should be modified to do this always...