microsoft / microsoft-ui-xaml

WinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.
MIT License
6.38k stars 683 forks source link

`The request is not supported.` during Bootstrap in Addin-Environment #9235

Open AchimStuy opened 1 year ago

AchimStuy commented 1 year ago

Describe the bug

With the transition of AutoCAD 2025 to .NET 6 I want to make use of WinUI. Automatic bootstrapping of Windows App SDK fails silently. Manual bootstrapping throws a COMException (0x80070032): The request is not supported. Not sure, whether it's AutoCAD being still in Alpha or me doing something wrong or Windows App SDK with the bug. How to diagnose further?

Steps to reproduce the bug

  1. Grab the latest AutoCAD alpha from https://feedback.autodesk.com
  2. Clone my minimal repro from https://github.com/AchimStuy/AutoCAD-WinUI.git
  3. Compile and NETLOAD in AutoCAD

Expected behavior

Bootstrap without exception or provide further diagnostics on why the request is not supported.

Screenshots

No response

NuGet package version

Windows App SDK 1.4.3: 1.4.231115000

Packaging type

Unpackaged

Windows version

Windows 11 version 22H2 (22621, 2022 Update)

IDE

Visual Studio 2022

Additional context

No response

Scottj1s commented 10 months ago

@AchimStuy for add-in scenarios like this, you might be able to ignore this condition (treat it as expected) by using the MddBootstrapInitializeOptions_OnPackageIdentity_NOOP policy. For C#, see the MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP compile define used here.

AchimStuy commented 9 months ago

@Scottj1s, thank you for your reply. Now I get TypeInitializationException in WinRT.ActivationFactory:

System.TypeInitializationException: The type initializer for 'WinRT.ActivationFactory`1' threw an exception.
 ---> System.Runtime.InteropServices.COMException (0x80040154): Class not registered (0x80040154 (REGDB_E_CLASSNOTREG))
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
   at WinRT.BaseActivationFactory..ctor(String typeNamespace, String typeFullName)
   at WinRT.ActivationFactory`1..ctor()
   at WinRT.ActivationFactory`1..cctor()
   --- End of inner exception stack trace ---
   at WinRT.ActivationFactory`1.As(Guid iid)
   at Microsoft.UI.Xaml.Application.Make___objRef_global__Microsoft_UI_Xaml_IApplicationStatics()
   at Microsoft.UI.Xaml.Application.get__objRef_global__Microsoft_UI_Xaml_IApplicationStatics()
   at Microsoft.UI.Xaml.Application.Start(ApplicationInitializationCallback callback)
   at WinUITest.Class1.ShowWinUI() in C:\Users\astuy\Desktop\WinUITest\AutoCAD-WinUI\Class1.cs:line 37
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()
myth384 commented 9 months ago

Hi @AchimStuy,

We are on the same boat, although I am trying to use WinUI 3 for Autodesk Inventor AddIns. Lets team up to make WinUI 3 possible for plugin type applications!

I'll share what I know so far. First of all, you didn't explicitly define the projects OutputType, it defaults to Library then. That is perfectly fine for plugin type applications, but automatic bootstrapping by default only works for executable projects. This behavior can be changed by setting WindowsAppSdkBootstrapInitialize to true in your project file. For now, I personally stick to manual bootstrapping in the entry point of my AddIn, it appears to work.

I came to the conclusion Application.Start() is not useful for our use case, as it only returns when the Application object is terminated. The host application freezes until then. What we need is a way to instantiate the Application singleton within the AppDomain of the running host application. I don't believe this is currently available in the WinUI API. Maybe it's even impossible to implement.

WindowsXamlManager.InitializeForCurrentThread() in your code gave me hope we are still able to use WinUI 3, though. But from what I have understood we have to use WinForm or WPF windows to host a XAML island. Autodesk Inventor has a WPF Application singleton available, which I have used extensively in the past. There is a good chance AutoCAD has this available as well.

@Scottj1s, what are your thoughts regarding our use case?

AchimStuy commented 9 months ago

Hi @myth384, thank you for joining! Inventor is next on my agenda.

Firstly: What were the keywords you were searching? Should I edit the Issue title in order for more people to join the discussion? And would you like to add your Inventor project to my repo, so we have everything in one place?

I had an error in reasoning and completely skipped bootstrapping. Manual bootstrapping works now, automatic bootstrapping not yet. And I need to compile <WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>. With this constellation I am also now at the unspecified XamlParseException during window creation:

Microsoft.UI.Xaml.Markup.XamlParseException
  HResult=0x802B000A
  Message=XAML parsing failed.
  Source=WinRT.Runtime
  StackTrace:
   at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|39_0(Int32 hr)
   at WinRT.ExceptionHelpers.ThrowExceptionForHR(Int32 hr)
   at ABI.Microsoft.UI.Xaml.IApplicationStaticsMethods.LoadComponent(IObjectReference _obj, Object component, Uri resourceLocator, ComponentResourceLocation componentResourceLocation)
   at Microsoft.UI.Xaml.Application.LoadComponent(Object component, Uri resourceLocator, ComponentResourceLocation componentResourceLocation)
   at WinUI4AutoCAD.BlankWindow1.InitializeComponent() in C:\Users\astuy\Desktop\WinUITest\AutoCAD-WinUI\WinUI4AutoCAD\obj\x64\Debug\net8.0-windows10.0.19041.0\BlankWindow1.g.i.cs:line 37

In my implementation I mainly looked at WindowsXamlHostBase, which also creates an App instance via XamlApplicationExtensions.GetOrCreateXamlMetadataContainer();. And I followed Instantiate the XamlApplication object in the entry point of MyWPFApp, which shows the App lifetime. But for me it's also only try and error.

Maybe also @KeanW @adamenagy or @cyrillef have an idea? (Unfortunately they're not automatically linked here.)

myth384 commented 9 months ago

Hi @AchimStuy ,

I stumbled upon this issue while searching for "AutoCAD". Whenever I seek information regarding the implementation of plug-in type applications, I typically search for names of well-known host applications with plug-in systems, such as various Autodesk and Office products. In my experience, I'm never the first to encounter obstacles. ;-)

I also came across WindowsXamlHost, which is part of the Community Toolkit. This class acts as a XAML control to easily host UWP user controls inside WPF or WinForms windows. It was introduced as a convenience wrapper for the UWP XAML Islands feature DesktopWindowXamlSource.

And here's where I have to disappoint you... Both classes are for hosting UWP controls, not WinUI 3. WindowsXamlHost was made for DesktopWindowXamlSource from the Microsoft UWP framework with the namespace Windows.UI.Xaml. Windows App SDK 1.4 introduced XAML islands for WinUI 3 with the namespace Microsoft.UI.Xaml. As you can see, the namespaces look almost the same, and I also got mixed up by this. With the introduction of XAML islands in Windows App SDK 1.4, the developers of the Community Toolkit decided to drop WindowsXamlHost. However, Microsoft only ported DesktopWindowXamlSource to WinUI 3, which is not really usable for efficient migration of UI elements. What we need is a host control like the one for UWP. I recently created an issue on the GitHub page of the Community Toolkit, which can be found here. But in my opinion, Microsoft should implement such control directly into WinUI 3.

What I actually think Microsoft should consider is making WinUI 3 easily usable for plug-in type applications, where multiple specialized Application objects can coexist in one AppDomain, and where WinUI 3 Windows can be instantiated from instead of having to use WinForms or WPF Windows with a host control for displaying WinUI 3. Maybe that's what this issue should be about.

myth384 commented 9 months ago

Hi @AchimStuy , I've just created a feature request in which I've aimed to define the scope of the use case as broadly as possible.