2

My app instantiates a COM component (global registration).
This COM component instantiates registration free components.
One of those sub-component is implementetd in C#.
If my app is not located in the same folder as the main COM component, it failed to instantatiate the C# COM component (but succeed for the other COM components).

WARNING: detailed explanations below ...

I have an application (Loader1) which loads a COM component (COM1, which is registration free) and this COM component loads as well several other COM components (which are themselves registration free).

  • Loader1
    • COM1
      • COM2
      • COM3
      • COM4
      • etc ...

But I must support the scenario where the loader use the COM1 component as a regular & registered COM component.
This has been working for several years without issues (just needed to sort out the manifest hell).

Now, we developped a new COM component in C# (COM interop). This component was made registration free as well (slightly different assembly dependency but works ok).

So we got:

  • Loader1
    • COM1
      • COM2
      • COM#

Loader1 got a manifest specifying it uses COM1.
COM1 got a manifest specifying it uses COM2 and COM#.
Everything is in the same directory and it works flawlessly.

NOW, when i try to use another loader (Loader2) which uses COM1 as a REGULAR COM component (COM1 is registered on the system and located in another directory), it fails to instatiate COM#.
To be more specific, COM1 is registered on the system, but COM2 and COM# are not (they are private assemblies only used by COM1).

To summarise the issue:

Loader2 in his own folder, instantiates COM1 as a regular COM component.
COM1 in his own folder got private assemblies, COM2, COM#. Those private assemblies are in the COM1 folder.
COM1 instantatiates COM2 successfully.
COM1 failed to instantiate COM#.

The HRESULT returned if 0x80070002, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND).
When i use FUSLOGVW.exe to see what the .net loader is doing, it seems .net is searching COM# in the application folder (Loader2 folder) and not the COM1 folder.
Somehow COM1 manifest is not used when searching for COM#.
But it is used when searching for COM2 ...

Well it is different systems.

Now, if I copy the Loader2 files to the folder where is located COM1 and its dependencies. Everything works fine.

So any idea, how to help the .net assembly loader to find the private assembly COM# from the COM1 folder and not the application folder ?

Julianis
  • 21
  • 1
  • That seems quite logical. I don't see why the system would load a component from some random place (I know it's not random, but Loader1 directory means nothing to Loader2 app context). For example you can ony specify a relative private path when loading components: https://learn.microsoft.com/en-us/windows/win32/sbscs/application-configuration-files (see 'probing' section), so either they are registered, either they are located where specified (note: "The additional directories are not required to be subdirectories of the directory of the assembly.") – Simon Mourier Aug 06 '19 at 15:06
  • Well Loader1 using COM1 as a private assembly is not the issue and it is the reason why Loader1 and COM1 are in the same directory. Let say Loader1/2 are using COM1 as a standard COM component located in his own folder. Then COM1 is using COM isolation and private assemblies. The COM free registration works for standard COM components (when COM1 instantiates COM2, it is searched in COM1 folder and not in the registry). But unfortunately, it doesnt work for C# COM components. – Julianis Aug 07 '19 at 09:54
  • Well I found a similar question: https://stackoverflow.com/questions/48272723/how-to-provide-a-private-side-by-side-manifest-that-correctly-locates-a-net-dll?rq=1 It seems there is no solution – Julianis Aug 07 '19 at 09:54
  • I found a solution going through the hosting API and creating an AppDomain. COM1 creates an AppDomain and configures it for usage with COM#. Then it creates the C# instance of the desired coclass (it creates directly the C# object). Then from the _ObjectHandle, I obtain the COM interface. So it skips the CoCreateInstance() ... It seems to work whatever the loader: native, .net, isolated or not. – Julianis Aug 08 '19 at 15:58

0 Answers0