Skip to content
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

Self-contained WinRT components don't work. #1141

Open
jlaanstra opened this issue Mar 18, 2022 · 23 comments
Open

Self-contained WinRT components don't work. #1141

jlaanstra opened this issue Mar 18, 2022 · 23 comments
Labels
authoring Related to authoring feature work enhancement New feature or request

Comments

@jlaanstra
Copy link
Collaborator

Describe the bug
WinRT.Host.dll doesn't work for a self-contained deployment. It requires .NET to be installed on the machine separately which can't be done with MSIX.

To Reproduce

  1. Modify the BgTaskComponent sample to deploy the WPF App as self-contained by adding true
  2. Deploy the package to a machine that doesn't have .NET framework packages installed.

Expected behavior
Toast task from the sample should work.

Actual behavior
Toast task does not work.

Version Info
CsWinRT 1.5.0

Additional context
N/A

@jlaanstra jlaanstra added the bug Something isn't working label Mar 18, 2022
@AaronRobinsonMSFT
Copy link
Member

AaronRobinsonMSFT commented Mar 19, 2022

This is a blocking issue that, as currently implemented, is not possible with the WinRT.Host. The root cause is use of the hostfxr_initialize_for_runtime_config API, which doesn't support a self-contained scenario. In order to support a self-contained scenario the hostfxr_initialize_for_dotnet_command_line API needs to be used. However, using this API and enabling self-contained library is not without concerns.

  1. The self-contained scenario is intentionally blocked for non-applications due concerns about enabling SxS in-proc versions of coreclr—which is not supported. Care must be taken to ensure the process that is loading the library will not be used by any other .NET library and inadvertently load another coreclr instance.

  2. There is no direct support in the .NET SDK for creating a self-contained library. This is by-design and related to concern (1).

  3. Using hostfxr_initialize_for_dotnet_command_line and then relying on hdt_load_assembly_and_get_function_pointer should be considered an anti-pattern for what users would desire. The issue has to do with which AssemblyLoadContext (ALC) the entry point assembly will be loaded into. Using hdt_load_assembly_and_get_function_pointer, the assembly maybe loaded again into a new isolated ALC as opposed to using the existing loaded instance in the default ALC. This has broad ramifications that need to be considered. Alternatively, in .NET 6 the hdt_get_function_pointer can be used which can load from the default ALC.

  4. It isn't clear how servicing is to be performed for applications or services. There are various security patching processes that will be ignorant of self-contained applications and if the service is running in a sensitive environment, this is a real concern.

/cc @vitek-karas @elinor-fung @agocke

@jlaanstra
Copy link
Collaborator Author

  1. The self-contained scenario is intentionally blocked for non-applications due concerns about enabling SxS in-proc versions of coreclr—which is not supported. Care must be taken to ensure the process that is loading the library will not be used by any other .NET library and inadvertently load another coreclr instance.

This should be easy to guarantee for packaged apps.

  1. It isn't clear how servicing is to be performed for applications or services. There are various security patching processes that will be ignorant of self-contained applications and if the service is running in a sensitive environment, this is a real concern.

MSIX packaged apps are all self-contained (no other ways to guarantee .NET is on the machine), so this isn't a new concern for a self-contained WinRT component right?

@AaronRobinsonMSFT
Copy link
Member

MSIX packaged apps are all self-contained (no other ways to guarantee .NET is on the machine), so this isn't a new concern for a self-contained WinRT component right?

That is predicated that CsWinRT is only targeting MSIX scenarios. From my understanding, CsWinRT doesn't require a packaged installation so the general concept should be factored into the cost of support and document how one handles servicing .NET assets.

@jlaanstra
Copy link
Collaborator Author

MSIX packaged apps are all self-contained (no other ways to guarantee .NET is on the machine), so this isn't a new concern for a self-contained WinRT component right?

That is predicated that CsWinRT is only targeting MSIX scenarios. From my understanding, CsWinRT doesn't require a packaged installation so the general concept should be factored into the cost of support and document how one handles servicing .NET assets.

Indeed CsWinRT doesn't require a packaged installation, but at the same time it currently doesn't block self-contained MSIX deployment and so I don't see any net-new concerns by allowing it for a WinRT component.

@jlaanstra
Copy link
Collaborator Author

jlaanstra commented Mar 21, 2022

An example of using https://github.com/AaronRobinsonMSFT/DNNE for self-contained components is here, in the NativeHost project of src/Samples/BgTaskComponent/BgTaskComponent.sln: https://github.com/jlaanstra/CsWinRT/tree/user/jlaans/self-contained

@angelazhangmsft angelazhangmsft added enhancement New feature or request authoring Related to authoring feature work and removed bug Something isn't working labels Mar 29, 2022
@angelazhangmsft
Copy link
Contributor

angelazhangmsft commented Apr 20, 2022

An example of using https://github.com/AaronRobinsonMSFT/DNNE for self-contained components is here, in the NativeHost project of src/Samples/BgTaskComponent/BgTaskComponent.sln: https://github.com/jlaanstra/CsWinRT/tree/user/jlaans/self-contained

@jlaanstra @AaronRobinsonMSFT - to clarify, is there a way to implement self-contained C# WinRT components, or is further work in CsWinRT required for that support?

@AaronRobinsonMSFT
Copy link
Member

or is further work in CsWinRT required for that support?

More work is needed. @jlaanstra was able to create a host that supports self-contained using DNNE but the built-in one needs to be updated to support the scenario. It is up to C#/WinRT to determine if self-contained is needed or not. There are UX and scenario limitations that need to be understood before officially supporting it.

@angelazhangmsft
Copy link
Contributor

Thanks @AaronRobinsonMSFT.

I've opened https://task.ms/39162576 to track this

@JohnMcPMS
Copy link
Member

I'm trying to author a component (.NET 6) that will be consumed by:

  1. A packaged C++ process
  2. A packaged C# process (different package)
  3. A PowerShell module

This issue has me worried that my packaged scenarios won't work without .NET 6 being installed. Given that these scenarios revolve around installation/setup of systems, there is a very real possibility of it not being present.

Am I understanding it correctly?

Fortunately, I think we could bootstrap ourselves if needed, but I don't want for that to be a requirement if possible (it may even be explicitly blocked from being one).

@whiskhub
Copy link

whiskhub commented Jul 5, 2024

How is it possible this is unresolved for so long? It means the feature is pretty much unusable for MSIX / Windows App SDK?

whiskhub added a commit to whiskhub/CsWinRT that referenced this issue Oct 6, 2024
Tries to fix microsoft#1141. Uses the same approach as commited in https://github.com/jlaanstra/CsWinRT/tree/user/jlaans/self-contained microsoft#1141 (comment) with DNNE, but within CsWinRT directly, avoiding additional binaries.
@whiskhub
Copy link

whiskhub commented Oct 6, 2024

I have looked into this myself and added self-contained support to CsWinRT in a fork, based on the implementation in #1141 (comment) but without DNNE and additional binaries.
I also added a WinUI 3 sample project: master...whiskhub:CsWinRT:feature/self-contained

I can confirm the self-contained runtime is loaded as expected in the backgroundTaskHost.exe with my fork, and GetActivationFactory within WinRT.Host.Shim managed code is successfully executed. However, the background task itself is not executed, with the exception being visible:

Exception thrown at 0x00007FFAD33DFE4C (KernelBase.dll) in backgroundTaskHost.exe: WinRT originate error - 0x80131513 : 'Method not found: 'System.Collections.Concurrent.ConcurrentDictionary`2<System.RuntimeTypeHandle,WinRT.IObjectReference> WinRT.IWinRTObject.get_QueryInterfaceCache()'.'.

You can also get the debugger to break on it, if you enable native debugging and set Visual Studio to break for Win32 Exceptions -> WinRT originate errors. This seems to be the same issue as with #1277, so there seems to be a more general problem here. To clarify, with the DNNE approach this error does not occur.
I was not able to find out the root cause - that's too deep for me :) Would highly appreciate it if anyone else has more insights!

@ekalchev
Copy link

ekalchev commented Oct 8, 2024

We recently migrated to MSIX and .NET 8 with a self-contained deployment strategy, as MSIX inherently requires this approach. Our aim is to leverage background tasks, but this issue presents a significant blocker for our architecture. From my understanding, there is currently no way for self-contained apps to host out-of-proc WINRT component written in .NET. This limitation affects not only background tasks but also context menu handlers, push notifications, and potentially other features we intend to implement. The inability to use these functionalities restricts our application’s capabilities significantly. We’re keen to see if there are any upcoming solutions or workarounds that might help us address these challenges.

@dongle-the-gadget
Copy link
Contributor

FYI, you can use Native AOT now, which are self-contained.

@whiskhub
Copy link

whiskhub commented Oct 8, 2024

FYI, you can use Native AOT now, which are self-contained.

Only if you make the entire app NativeAOT, which currently is unfeasible with the amount of hurdles it has. It's not possible to have your authored component in a referenced project be NativeAOT and the main app project be self-contained.

@dongle-the-gadget
Copy link
Contributor

dongle-the-gadget commented Oct 8, 2024

Only if you make the entire app NativeAOT

You don't need to, only the class library itself is required to use Native AOT. Native AOT deployment should not affect your main app.

@whiskhub
Copy link

whiskhub commented Oct 8, 2024

You don't need to, only the class library itself is required to use Native AOT. Native AOT deployment should not affect your main app.

It does not work however, when setting <PublishAot>true</PublishAot> for the library while the main app is <SelfContained>true</SelfContained> in the same solution, an error occurs. I am not sure if it is a bug or unsupported behavior.

NETSDK1130 BgTaskComponent.winmd cannot be referenced. Referencing a Windows Metadata component directly when targeting .NET 5 or higher is not supported. For more information, see https://aka.ms/netsdk1130 WinUi3BackgroundTask C:\Program Files\dotnet\sdk\8.0.400\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.targets

@dongle-the-gadget
Copy link
Contributor

You package the two projects independently, not reference the AOT project in the non-AOT project.

@whiskhub
Copy link

whiskhub commented Oct 8, 2024

You package the two projects independently, not reference the AOT project in the non-AOT project.

I guess that is a workaround, but a painful one. Having to build and distribute a NuGet package, especially for "local" projects, is far more complicated, than just referencing the project. Additionally, the AOT binary will be larger than just referencing existing runtime.

@dongle-the-gadget
Copy link
Contributor

WinRT components already work framework dependent. This issue is about self-contained deployments, which is already large.

@whiskhub
Copy link

whiskhub commented Oct 8, 2024

WinRT components already work framework dependent. This issue is about self-contained deployments, which is already large.

Yes, but having an AOT CsWinRT library next to a self-contained app in the same MSIX will also duplicate the runtime to some extent, even with trimming.

@dongle-the-gadget
Copy link
Contributor

Wouldn't it be the same if they both use self-contained regardless?

@whiskhub
Copy link

whiskhub commented Oct 8, 2024

No, the CsWinRT component and the app would use the same self-contained runtime within the same solution / MSIX package. No duplicates.

@whiskhub
Copy link

whiskhub commented Oct 16, 2024

Exception thrown at 0x00007FFAD33DFE4C (KernelBase.dll) in backgroundTaskHost.exe: WinRT originate error - 0x80131513 : 'Method not found: 'System.Collections.Concurrent.ConcurrentDictionary`2<System.RuntimeTypeHandle,WinRT.IObjectReference> WinRT.IWinRTObject.get_QueryInterfaceCache()'.'.

I found out the error has something to do with the AssemblyLoadContext in the WinRT.Host.Shim. https://github.com/microsoft/CsWinRT/blob/master/src/Authoring/WinRT.Host.Shim/Module.cs#L76-L106:

Normally, the WinRT.Runtime assembly should be loaded for each AssemblyLoadContext in the protected override Assembly Load(AssemblyName assemblyName), while for all other assemblies null is returned. This should trigger the AssemblyLoadContext.Default.Resolving event, causing the other assemblies to be loaded there in the main ALC. But this event is never raised in the self-contained scenario. So no assembly except the WinRT runtime and System.Private.CoreLib assembly are actually loaded, causing the missing methods.

Replacing the entire construct with a simple Assembly.LoadFrom() fixes the error. But there is a reason the ALC construct was added after all...

I don't know what the reason is and how to fix it yet, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
authoring Related to authoring feature work enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants