1

Winforms-application in C#, .net 4.5.2.

I wish to handle all communication with a private COM-assembly in a thread. However, I get

"This operation failed because the QueryInterface call on the COM component
for the interface with IID xxxx-xxx failed due to the following error: No
such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)".

If I use regsvr or the installation process to register the assembly it works as intended, but I want the assembly to be private due to previous dll hell issues.

If I handle the dll from the main thread, it works as intended, but I would like to do this in the thread.

The thread is looking in the correct directory, I can find the assembly using reflection (but that makes the rest of the coding quite difficult...).

As far as I can tell, you cannot use multithreaded apartment in winforms, and additionally, this is likely not a good idea.

So... is it possible to access a private assembly from a thread? What am I missing?

Some more info:

theProgram.exe.manifest:

<?xml version="1.0" encoding="utf-8"?>
<assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
  <assemblyIdentity name="theProgram.exe" version="5.0.0.0" processorArchitecture="x86" type="win32" />
  <dependency>
    <dependentAssembly asmv2:dependencyType="install" asmv2:codebase="theCom.dll.manifest" asmv2:size="756">
      <assemblyIdentity name="theCom.dll" version="1.0.0.0" type="win32" />
      <hash xmlns="urn:schemas-microsoft-com:asm.v2">
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
        <dsig:DigestValue>m2iQCXnuLAKN5aCVPExSBjLBBxzrHjXzs8s6pVAhnP8=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>
</assembly>

The manifest for the com:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

<assemblyIdentity
    type="win32"
    name="theCom.dll"
    version="1.0.0.0" />

<file name = "theCom.dll">

<comClass
    clsid="{256DE321-02F0-4238-8116-2A40E62DDBFE}"
    threadingModel = "Apartment" />

<typelib tlbid="{2EC9A174-C7CA-4DF8-ABA0-47095DA87277}"
       version="1.0" helpdir=""/>

</file>

<comInterfaceExternalProxyStub 
    name="InterfaceThingy"
    iid="{6ECD465F-DD96-4DBE-A844-E71237881C1B}" 
    proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
    baseInterface="{00000000-0000-0000-C000-000000000046}"
    tlbid = "{2EC9A174-C7CA-4DF8-ABA0-47095DA87277}" />

</assembly>

Creation of the thread:

myThread = new Thread(threadClass.StartMethod);
myThread.Start();

Instantiation of a type from the com. Works in the main thread regardless of registration, in the subthread only if the COM is registered.

if (m_Type == null)
     m_Type = new TypeCtl();
Camilla W
  • 41
  • 7
  • 3
    I think we're going to need to see some code to figure this out. – Robert Harvey Jun 22 '20 at 16:12
  • What part of it? The COM is added as a reference via a manifest, the Thread is a "normal" Thread.Thread. – Camilla W Jun 23 '20 at 08:27
  • On which thread do you create it and on which thread do you use it? – Thomas Weller Jun 23 '20 at 08:31
  • This is about COM code, not reflection, threads or private assemblies. COM doesn't have assemblies for one, it has interfaces and classes. The error says the (missing) code tried to use a non-existent type. Without the code, it's impossible to guess what's wrong – Panagiotis Kanavos Jun 23 '20 at 08:34
  • `If I use regsvr or the installation process to register the assembly it works as intended` that's the easiest way to use a COM component. The other is to load it locally, which is a bit more prone to DLL hell, not the other way round. `I want the assembly to be private due to previous dll hell issues.` what issues? How did you load the DLL? – Panagiotis Kanavos Jun 23 '20 at 08:37
  • @PanagiotisKanavos When another version of the COM is registered to GAC, the application uses that one instead. All of the versions of the COM are not compatible. If I'm not mistaken, this is dll-hell and using private assemblies instead is recommended to avoid it – Camilla W Jun 23 '20 at 12:56
  • @ThomasWeller I create it on the thread I'm trying to use it on. It works without running regsvr on the main gui-thread, but not on a thread that thread creates. If I run regsvr it works on either thread. – Camilla W Jun 23 '20 at 12:58
  • @CamillaW as it should. `All of the versions of the COM are not compatible.` that's the developer's responsibility, to create backward compatible APIs at least. That's why there are interfaces like `IMyInterface` and `IMyInterface2` with extra methods. Dll hell is what happened here - multiple versions in the same machine, loaded the wrong way without paying attention to versioning – Panagiotis Kanavos Jun 23 '20 at 13:00
  • That's not going to work *unless* you use the GAC. – Panagiotis Kanavos Jun 23 '20 at 13:02
  • @PanagiotisKanavos Well, yes, but I have not built the COM and moving from it completely will take too much time, so I need a solution within the bounds of the question. – Camilla W Jun 23 '20 at 13:03
  • @PanagiotisKanavos You mean that it is impossible to use a private COM in a subthread? – Camilla W Jun 23 '20 at 13:05
  • Without any code or any specifics, one can only point to duplicate questions like [this one](https://stackoverflow.com/questions/1198810/force-net-interop-to-use-local-com-dll). – Panagiotis Kanavos Jun 23 '20 at 13:05
  • @PanagiotisKanavos I already have registration free COM set up, problem is that the subthread doesn't find the COM unless I register it. – Camilla W Jun 23 '20 at 13:07
  • It finds it just fine, at issue is that it can't marshal the interface. Bad comInterfaceExternalProxyStub. From the [docs](https://learn.microsoft.com/en-us/windows/win32/sbscs/assembly-manifests): *A subelement of a file element* – Hans Passant Jun 25 '20 at 21:14

0 Answers0