MicrosoftDocs / winrt-related

WinRT related reference content for developing Microsoft Universal Windows Platform (UWP) apps
Creative Commons Attribution 4.0 International
76 stars 89 forks source link

How does "com4:ManagedInProcessServer" work under a MSIX packaging scenario? #385

Closed EZForever closed 18 hours ago

EZForever commented 9 months ago

I'm trying to create a MSIX package for a classic Windows desktop app. The app is written in C# (.NET Framework 4.7.2), and it's running perfectly both before and after packaging.

The problem is that the app exposes a COM class library (also written in C#) for interop with other apps. The original installer of this app registers the COM library with "regasm.exe". Given that MSIX have the ability to expose COM servers, namely with the "windows.comServer" extension, I've tried adding the following extension to package manifest, but it does not work as intended:

<com:Extension Category="windows.comServer">
    <com:ComServer>
        <com:SurrogateServer DisplayName="TheApp Class Library">
            <com:Class Id="8ae249dd-05f8-403e-ac32-00feab49c1f5" Path="TheApp.Library.dll" ThreadingModel="STA" />
        </com:SurrogateServer>
    </com:ComServer>
</com:Extension>

After some research I've found that C# COM libraries registers differently with normal ones; namely it requires a few more entries than DLL path and CLSID written into the registry.

Digging through the documents, I've found that "com4:ManagedInProcessServer" seems to be just what I needed. So I've tried to use the following extension instead:

<com4:Extension Category="windows.comServer">
    <com4:ComServer>
        <com4:ManagedInProcessServer Assembly="TheApp.Library, Version=1.0.0.0, Culture=neutral" RuntimeVersion="v4.0.30319">
            <com4:Class Id="8ae249dd-05f8-403e-ac32-00feab49c1f5" ImplementationClass="TheApp.Library.ExtensionManager" ThreadingModel="STA" Virtualization="disabled" />
        </com4:ManagedInProcessServer>
    </com4:ComServer>
</com4:Extension>

But it still does not work. In fact, this time even the "HKEY_CLASSES_ROOT\CLSID\{...}" registry entries do not get generated. I've checked the AppX deployment logs and no error has ever occurred during package installation. It is as if the extension declaration is not there.

What confuses me more is that "com4:ManagedInProcessServer" does not allow specifying codebase for the assembly. With "regasm.exe" one can specify the full path to COM library with "/codebase", but "com4:ManagedInProcessServer" does not seem to be allowing this.

I've been looking for relevant information for quite some time, but all I could find is the single document page on XML schema (linked above), with no real-world code examples. (And by "no" I mean literally ZERO code example on Internet.) I would like to know if "com4:ManagedInProcessServer" works under the situation described above, and if not so, what should I do to have a C# COM library exposed by a MSIX package?

If it matters, I'm using the latest version of Visual Studio Community 2022 with SDK version 10.0.22621.0. The MSIX package is to be deployed on a Windows 11 23H2 system.


Document Details

Do not edit this section. It is required for learn.microsoft.com ➟ GitHub issue linking.

drewbatgit commented 18 hours ago

Hello, sorry for the delayed response. I tracked down a subject matter expert who offered the following response to your issue. Unfortunately, the TL;DR is that yours is not a broadly supported scenario, so it may not be possible. But the SME did offer some potential workarounds. For further support, I recommend you open an issue at Microsoft Q&A.

Key Points:

  1. MSIX Limitations: Exposing in-process COM servers is not well-supported in MSIX due to ACL restrictions. Most packages cannot successfully expose inproc COM servers for external use.
  2. Workarounds: Various workarounds are required depending on the specific use case:
    • com:ProxyStub: Works by copying DLLs to a location accessible to other apps, but this is not a generalized solution.
    • Sparse Packages: Mainly target sparse packages where the installer sets up the necessary ACLs.
    • Manifest Extensions: Needed for COM registrations, but managed assemblies must be in the real Global Assembly Cache (GAC), not just visible within the package.
    • Surrogate Server: Apps using in-process COM servers may need to implement a surrogate server to handle their DLLs.

ManagedInProcessServer: Requires registry entries and real GAC presence, with no official manifest syntax for adding arbitrary assemblies to the GAC.

Proxy/Stub DLLs:

.NET Framework/Desktop CLR Limitation:

.NET Core: Has a different method for exposing COM classes that should work with com:SurrogateServer.

Conclusion: The scenario is complex with no one-size-fits-all solution. Developers need to navigate various workarounds and may require detailed conceptual documentation to guide them based on their specific requirements.