Skip to content

Integrate Shmueli's ComServer into CsWinRT #1995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from

Conversation

beervoley
Copy link

@beervoley beervoley requested review from manodasanW and shmuelie May 20, 2025 07:20
@hez2010
Copy link
Contributor

hez2010 commented May 21, 2025

I don't get why we would need yet another standalone WinRT server implementation and additional ComWrappers when it can already be achieved by passing the generated GetActivationFactory method to RoRegisterActivationFactories and using the ComWrappers provided by CsWinRT.
See https://github.com/hez2010/WinRTServer/blob/master/WinRTServer%2FProgram.cs

@dongle-the-gadget
Copy link
Contributor

I don't get why we would need yet another standalone WinRT server implementation

My guess is that it has to do with App Actions, announced in Build.

additional ComWrappers

Separation of concerns?

@manodasanW
Copy link
Member

I don't get why we would need yet another standalone WinRT server implementation and additional ComWrappers when it can already be achieved by passing the generated GetActivationFactory method to RoRegisterActivationFactories and using the ComWrappers provided by CsWinRT. See https://github.com/hez2010/WinRTServer/blob/master/WinRTServer%2FProgram.cs

The goal behind this PR is to provide a higher-level abstraction around this and also add features to it such as lifetime management as there are going to be more scenarios relying on this support. The lifetime management piece also sounds like it is going to need to be able to keep track of the instances for which CCWs are created for in the server, so it is going to achieve that by deriving from DefaultComWrappers. But that will be initialized as the one CsWinRT's uses. That part isn't there yet but will probably be added in a follow up. Otherwise, yes, it would have made sense just to use CsWinRT's ComWrappers rather than creating a new instance,

using System;
using System.Runtime.Versioning;

namespace ComServerHelpers;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really think about what actual namespace names to use. And type names.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your suggestion?

/// </returns>
/// <seealso href="https://learn.microsoft.com/en-us/previous-versions/br205771(v=vs.85)">DllGetActivationFactory entry point</seealso>
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
internal unsafe delegate HRESULT DllGetActivationFactory(HSTRING activatableClassId, IActivationFactory** factory);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not be marshalling function pointers from delegates. Can we just use [UnmanagedCallersOnly]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to comment this, but they got local state that they are maintaining.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sergio0694 any way around this while maintaining local state?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you have more than one instance of a given COM server class at the same time?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, definitely.

/// <threadsafety static="true" instance="false"/>
[SupportedOSPlatform("windows8.0")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1724", Justification = "No better idea")]
public sealed class WinRtServer : IDisposable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely let's not use "WinRt" as a type name. Should at the very least be "WinRT".
Ideally this should eventually be "WindowsRuntimeServer" in 3.0. We can do that now or later,

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving typenames/namespace changing to be very last changes.

public unsafe WinRtServer()
{
activationFactoryCallbackWrapper = ActivationFactoryCallback;
activationFactoryCallbackPointer = (delegate* unmanaged[Stdcall]<HSTRING, IActivationFactory**, HRESULT>)Marshal.GetFunctionPointerForDelegate(activationFactoryCallbackWrapper);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah definitely let's not do this. Use a function pointer directly instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callback here relies on state, so I'm not sure about the feasibility of this.

@Sergio0694 Sergio0694 requested a review from jkoritzinsky May 23, 2025 16:10
@Sergio0694
Copy link
Member

Closing this -- we discussed this offline and we're going to move this to a separate repo and NuGet package, rather than merging it into the CsWinRT repo and shipping it as part of the CsWinRT package. This follows a similar approach to what WindowsAppSDK has also done with the new package split, making the various components more modular and a-la-carte. In particular:

  • Maintaining the codebase gets simpler for everyone (both on the CsWinRT side and ComServer side)
  • Each component can have its own (semantic) versioning, without a need to align every release (and breaking changes)
    • Even more so with CsWinRT 3.0 on the horizon, having two independent packages is especially convenient
  • Folks that prefer to use their own custom infrastructure for OOP servers can do so, without taking a dependency on this at all

We'll be moving the code from this PR to continue that work, so thank you everyone for the reviews, those still helped! 😄

@Sergio0694 Sergio0694 closed this Jun 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants