Embed a Registration-Free COM manifest into a C# dll with native/managed environment
Asked Answered
L

1

4

I'm currently working on a mixed native / managed application chain, which employs registration-free COM. The following image illustrates this:

com

The C# wrapper DLL has been created using the tlbimp.exe utility. This allows each of the C# executables to access the native types and methods in the COM DLL. The COM DLL itself employs a server based RegFree COM manifest.

Everything works fine, when the client based RegFree COM manifests are embedded in the C# executables. However, I would like to move and unify these manifest files into the C# DLL, which would ease maintenance and synchronization of version info significantly.

Because Visual Studio doesn't provide an option to embed a manifest file into a C# class library, I have tried to extract, modify, and re-embed the DLL's default manifest with the manifest tool (mt.exe). This seems to have worked, as the C# DLL now exposes the following manifest, when being queried with mt:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity name="FirstClient" version="1.0.0.0" processorArchitecture="msil"></assemblyIdentity><file name="FirstClient.dll" hashalg="SHA1"></file>
<dependency>
            <dependentAssembly>
                        <assemblyIdentity type="win32" name="atl" version="1.0.0.0"></assemblyIdentity>
            </dependentAssembly>
</dependency>
</assembly> 

However, the executables refuse to work, each one complaining about the COM class factory not being able to find the missing COM module.

Is there something I have overlooked here? Thanks.

Langbehn answered 24/9, 2014 at 19:6 Comment(6)
@HansPassant Thanks, I didn't know it was possible to add manifests to class libraries in VS. Regarding your second remark: Yes, it would be great if I could avoid the extra TLB dll. However, the Visual C# dll project won't let me add a reference to the COM tlb, or the COM dll itself. It complains about these files not being COM components. That's why I've relied on the TLB wrapper so far.Langbehn
Hang on, there's another problem, Windows will never look in the DLL for the manifest. They are not loaded normally, no LoadLibrary() call, so the Windows loader has no reason to go looking for an embedded manifest. You'll have to do it in software, pinvoke CreateActCtx(). Also used in .NET, search the Reference Source it.Elfin
@Langbehn could you please provide more information in your answer as to how you did this? I have the exact same issue as you.Greco
@Greco Take a look at this tutorial, which describes the API pretty well.Langbehn
Thanks for that link Aurora, so you just surrounded all calls to the COM library within the C# library with ActCtx calls? Might have to give it another shot.Greco
Yes, each COM call needs to be placed inside an ActivateActCtx() - DeactivateActCtx() pair. First however, you'll need to create the activation context via CreateActCtx(). When you're done, destroy it with ReleaseActCtx().Langbehn
L
1

I got it working by pinvoking the appropriate Activation Context functions. Thanks to Hans Passant for the hint.

Langbehn answered 26/9, 2014 at 18:26 Comment(1)
Yes, .Net and most other scripting languages need to do this.Jerricajerrie

© 2022 - 2024 — McMap. All rights reserved.