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

When publishing AOT, C#/WinRT throws System.NotSupportedException: 'Cannot retrieve a helper type for generic public type 'Windows.Foundation.IAsyncOperation`1[System.Boolean]'.' #1871

Open
smourier opened this issue Nov 15, 2024 · 4 comments

Comments

@smourier
Copy link

Description

I'm developing a WinUI3 application. When not publishing AOT, it works, but when adding <PublishAot>true</PublishAot>, it throws

System.NotSupportedException: 'Cannot retrieve a helper type for generic public type 'Windows.Foundation.IAsyncOperation`1[System.Boolean]'.'

Full stack trace:

[Exception] WinRT.Runtime.dll!WinRT.TypeExtensions.FindHelperType(System.Type type, bool throwIfNotAotSupported)	Unknown
[Exception] WinRT.Runtime.dll!WinRT.IWinRTObject.IsInterfaceImplementedFallback(System.RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)	Unknown
[Exception] WinRT.Runtime.dll!WinRT.IWinRTObject.System.Runtime.InteropServices.IDynamicInterfaceCastable.IsInterfaceImplemented(System.RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)	Unknown
Microsoft.Windows.SDK.NET.dll!Windows.Graphics.Printing.PrintManagerInterop.ShowPrintUIForWindowAsync(nint appWindow)	Unknown
WinUIApp.dll!WinUIApp.MainWindow.myButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) Line 19	C#
Microsoft.WinUI.dll!WinRT._EventSource_global__Microsoft_UI_Xaml_RoutedEventHandler.EventState.GetEventInvoke.AnonymousMethod__1_0(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)	Unknown
Microsoft.WinUI.dll!ABI.Microsoft.UI.Xaml.RoutedEventHandler.Do_Abi_Invoke(nint thisPtr, nint sender, nint e)	Unknown
[Native to Managed Transition]	
[Managed to Native Transition]	
Microsoft.WinUI.dll!ABI.Microsoft.UI.Xaml.IApplicationStaticsMethods.Start(WinRT.IObjectReference _obj, Microsoft.UI.Xaml.ApplicationInitializationCallback callback)	Unknown
Microsoft.WinUI.dll!Microsoft.UI.Xaml.Application.Start(Microsoft.UI.Xaml.ApplicationInitializationCallback callback)	Unknown
WinUIApp.dll!WinUIApp.Program.Main(string[] args) Line 26	C#

Steps To Reproduce

To reproduce just create a WinUI3 blank project with latest Visual Studio 17.12.0, and modify the MainWindow.xaml.cs like this:

using System;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Windows.Graphics.Printing;

namespace WinUIApp;

public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private async void myButton_Click(object sender, RoutedEventArgs e)
    {
        var printMananager = PrintManagerInterop.GetForWindow(Win32Interop.GetWindowFromWindowId(AppWindow.Id));
        printMananager.PrintTaskRequested += (s, e) => { };
        await PrintManagerInterop.ShowPrintUIForWindowAsync(Win32Interop.GetWindowFromWindowId(AppWindow.Id));
    }
}

With standard settings, just run and it will fail on ShowPrintUIForWindowAsync with a COM exception but that's expected.

Now change the project settings to add PublishAot, and Rebuild (you must rebuild, a simple build is usually not enough here), here is mine:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net9.0-windows10.0.19041.0</TargetFramework>
    <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
    <RootNamespace>WinUIApp</RootNamespace>
    <ApplicationManifest>app.manifest</ApplicationManifest>
    <Platforms>x86;x64;ARM64</Platforms>
    <RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
    <PublishProfile>win-$(Platform).pubxml</PublishProfile>
    <UseWinUI>true</UseWinUI>
    <EnableMsixTooling>true</EnableMsixTooling>
    <Nullable>enable</Nullable>
    <PublishAot>true</PublishAot>
    <WindowsSdkPackageVersion>10.0.26100.57</WindowsSdkPackageVersion>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="Assets\SplashScreen.scale-200.png" />
    <Content Include="Assets\LockScreenLogo.scale-200.png" />
    <Content Include="Assets\Square150x150Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
    <Content Include="Assets\StoreLogo.png" />
    <Content Include="Assets\Wide310x150Logo.scale-200.png" />
  </ItemGroup>

  <ItemGroup>
    <Manifest Include="$(ApplicationManifest)" />
  </ItemGroup>

  <ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
    <ProjectCapability Include="Msix" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
    <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.240923002" />
    <PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
  </ItemGroup>

  <PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
    <HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
  </PropertyGroup>

  <!-- Publish Properties -->
  <PropertyGroup>
    <PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
    <PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
    <PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
    <PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
  </PropertyGroup>
</Project>

I've tried .NET 8 and 9, I've also tested with an explicit latest C#/WinRT and WindowsSdkPackageVersion references but it's the same.

Expected Behavior

It should not fail with a System.NotSupportedException.

Version Info

Visual Studio 17.12.0
C#/WinRT 2.2.0
.NET 9.0.0 or .NET 8.0.11

Additional Context

I don't know of any workaround, but it would be welcome.

@dongle-the-gadget
Copy link
Contributor

dongle-the-gadget commented Nov 17, 2024

In the meantime, the signature of this could be changed to return an IAsyncOperation<bool>, which should work with AOT mode:

Object ShowPrintUIForWindowAsync(

However, I don't think a more general solution to CsWinRT's existing usage pattern (casting from WinRT.IInspectable to a generic WinRT interface using IDynamicInterfaceCastable) would be possible without new projections).

@smourier
Copy link
Author

Thanks,

Not sure if I'm supposed to do anything from here

@dongle-the-gadget
Copy link
Contributor

dongle-the-gadget commented Nov 21, 2024

Does MarshalInterface<IAsyncOperation<bool>>.FromAbi(MarshalInspectable<object>.FromManaged(printManager)); work?

@smourier
Copy link
Author

Does MarshalInterface<IAsyncOperation<bool>>.FromAbi(MarshalInspectable<object>.FromManaged(printManager)); work?

but the problem is on PrintManagerInterop.ShowPrintUIForWindowAsync not on printManager?

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

No branches or pull requests

2 participants