-
Notifications
You must be signed in to change notification settings - Fork 329
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
WinAppSdk is difficult to use with reg-free WinRT due to class/file naming, pairs #2352
Comments
TL;DR WinAppSDK uses #2 ByDesign, for performance and complexity reasons. What you call "non-ideal layout" implies the projections' resolution is ideal, which isn't true. It's simple, but not necessarily best. As in WinAppSDK's case. #1 is hugely invasively and doesn't solve all the problems. #3 is a projection-specific answer, requires new designs and complicated new machinery, and doesn't solve all the problems without devolving to #1 but with more work. We discussed this at length last year before deciding to embrace manifested solutions instead of language projection's manifest-free option. Not all component authors face the same choices so YMM but, for WinAppSDK, this is an intentional decision for good reasons. Before discussing further it helps to understand the options available and their tradeoffs. There are 3 ways to resolve a packaged WinRT's activatable class id (ACID): A. Via the process' package graph. Requires using WinAppSDK/MSIX and the ACID defined in WinAppSDK's Your option #1 assumes resolution C. Caller uses OS mechanisms as well as its own hunting for a matching file, where the filename is named the same as the runtimeclass' namespace or prefix, e.g. C#/WinRT and C++/WinRT can find a theoretical connection object with the ACID
until 1st success or none match and not found. This is sometimes referred to as the 'manifest-free' option. The downsides are performance, required filenames and non-trivial objects (in both breadth and depth).
The manifest-free solution is convenient for simple cases, and likewise the object model and performance impacts are small. Larger more complex designs don't far so well with the manifest-free option and better suited to the manifested options. MSIX's Alas, the WinAppSDK/Self-Contained model makes that solution a non-option. We know the ACIDs/DLLs layout and can define those relations in metadata ( NOTE: You don't need to provide a single And that's why WinAppSDK uses manifested solutions for its WinRT components. Other libraries may reach different decisions as they face different tradeoffs.
Use WinAppSDK via MSIX packages. Then no need for RegFreeWinRT thus no problemo :-) |
Thanks, sounds like this is intentional then. Will close. My guidance to language projection authors will be to embed the manifest (if they have the tooling to do so) or parse the manifest and deal with the class id<->file map at codegen time. I'm working on the latter approach with the windows-app rust crate at the moment. |
I'd advise caution. The downside to the SxS manifest is the 'registration info' is separate from the implementation. Changes to the implementation can impact the registration info, e.g. if v1.2.3 adds a new runtimeclass not in v1.2.2. If/when we use internal runtimeclasses amongst WinAppSDK components not exposed as public APIs, you need to use the same registration info as the matching implementation. Incomplete or mismatched registration info vs runtime can produce 'undefined behavior'. I forgot to ask but thanks for reminding me...
What WinRT component recommendations are you referring to? Got link?
Can you elaborate? |
I think you're warning folks to ensure they keep up on manifests. That's a fair warning and something I automate (for Rust). Every time I regenerate the crate for a major/minor/bugfix, we will retrieve a fresh copy. Sound good?
It's linked at the top, but easy to miss. Here's another copy. (Admittedly, this is in the context of C++/WinRT, which you addressed above.)
There's no easy/portable/idiomatic way to copy the manifest around (or embed it into the image) at this time. It's a known gap in the ecosystem right now. 😞 |
More like not to forget the manifest is tightly coupled with and part of the implementation. If you're using WinAppSDK's nuget and MSbuild support ItJustWorks™. If you're coloring outside the lines make sure to color all the lines ;-)
Yes. Just noting as the manifest is something easily overlooked.
Thanks! I see that doesn't mention the complex case or the namespace-depth concern. We should correct that. And by we I mean... @BenJKuhn we should expand the guidance for the complex cases (like WinAppSDK :-) that don't fit so well with the simple filename/lookup scheme. https://task.ms/38821629
Which ecosystem, Rust or Windows? |
I'm not sure how helpful it would be to update the docs to cover WinAppSDK's implementation details - I can't imagine we'd really recommend anyone else building something this complex as a best practice, which is what the docs are talking about. |
Rust. |
Not the ask. WinAppSDK is merely an instance of a complex implementation not served as well by the manifest-free guidance as a manifested one. We should document guidance for component authors not in the 'simple' case.
Office. Photoshop. SAP. Lots other realworld codebases don't fit so well in the manifest-free model. I'm not saying we recommend developers write complex systems but it happens. When they do, we should have guidance (other than "rewrite your complex implementation to fit the manifest-free model"). |
:-( Rust crates have no convention for it? Yet? ;-) |
Is there some reason that resolutions A and B wouldn't work just as well with option 1 as with the existing layout? If I understand correctly, the manifest avoids the need to crawl the filesystem, regardless of whether the class/file relationship supports registration-free activation or not. In other words, resolution C carries the performance penalty, not option 1.
Is that the class implementation, the activation factory for that class, the metadata...? My understanding is that registration-free activation finds the DLL by relying on a naming convention, loads it and calls the DllGetActivationFactory entry point to get an activation factory. So the only real requirement is that the DLL is able to locate the activation factory for the given runtime class. The class implementation itself can be anywhere. Even the activation factory can be implemented elsewhere, as long as the entry point knows how to locate it. The DLL could be just a stub used for registration-free activation, perhaps comparable to an API set. However, I'm likely missing something. For instance, I don't know how the metadata is located for a third-party component. |
Problem
Windows App SDK (WAS) 1.1-preview1 added the ability to ship as part of a self-contained application. What this generally means is that WAS components are now activatable without registration (registration-free WinRT). Instead of relying on registration information stored in the Windows Registry, WAS tooling now/currently stuffs a large manifest into your app replicating that function.
To support this feature outside Visual Studio/Msbuild C++/C#, developers must:
To avoid manifestation altogether, projections such as C++/WinRT and C#/WinRT alternatively turn to a simple algorithm to locate activatable classes and their activation factory. These projections:
Unfortunately, WAS does not adhere to best WinRT component naming practices. WAS files have unexpected names and/or host classes that don't have related namespaces.
Here's a snippet of what the class <-> file relationship looks like today:
Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyRank
Microsoft.Windows.System.EnvironmentManager
...
Microsoft.UI.Xaml.Controls.ItemClickEventArgs
Microsoft.UI.Xaml.Controls.SelectionChangedEventArgs
Microsoft.UI.Xaml.Controls.SemanticZoomViewChangedEventArgs
...
Microsoft.UI.Xaml.Controls.XamlControlsResources
Microsoft.UI.Private.Controls.MUXControlsTestHooks
Microsoft.UI.Xaml.Controls.Primitives.CornerRadiusToThicknessConverter
Microsoft.UI.Xaml.Controls.Primitives.CornerRadiusFilterConverter
...
Microsoft.UI.Text.TextConstants
Microsoft.Web.WebView2.Core.CoreWebView2Environment
Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions
Microsoft.UI.Dispatching.DispatcherQueueController
...
(The full table, as of 1.1-preview1, can be found here.)
Observe in the above snippet:
Microsoft.WindowsAppRuntime.dll
hosts classes in theMicrosoft.Windows.ApplicationModel.*
andMicrosoft.Windows.System.*
namespacesMicrosoft.UI.Xaml.dll
andMicrosoft.UI.Xaml.Controls.dll
host classes in theMicrosoft.UI.Xaml.Controls.*
namespaceWinUIEdit.dll
hosts classes in theMicrosoft.UI.Text
namespaceI explored the possibility of simply renaming the libraries to compatible names, but
Microsoft.UI.dll
andMicrosoft.UI.Xaml.dll
both contain types that would fail the aforementioned search algorithm.Considered workarounds/solutions
Rename all WAS libraries and move the classes to the right spots.
Requires WAS code change. Could be considered a major change (2.0).
Continue using the internal/external manifest.
This does not follow WinRT component recommendations, is generally non-idiomatic, and is unfriendly for some projections (e.g. Rust).
Change language projections to deal with non-ideal layout.
Requires all projections to change. Involves working with sensitive projection code.
Projections could perhaps:
Did I miss any?
The text was updated successfully, but these errors were encountered: