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

Weird UWP reference in unexpected places #1059

Open
petroemil opened this issue Oct 24, 2019 · 8 comments
Open

Weird UWP reference in unexpected places #1059

petroemil opened this issue Oct 24, 2019 · 8 comments

Comments

@petroemil
Copy link

The symptom

We ran into an interesting bug (?) recently, while updating our services to .NET Core we suddenly started receiving strange build errors, like:

The type 'IAsyncAction' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.

The type 'IAsyncActionWithProgress<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.

The type 'IAsyncOperation<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.

The type 'IAsyncOperationWithProgress<,>' is defined in an assembly that is not referenced. You must add a reference to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.

These errors were pointing to lines where we directly awaited IObservables, like

await Observable.Return("Hello World");

The clue

As I've been rigorously scanning through our dependencies and project file definitions, one thing stood out, that the System.Reactive NuGet package has a reference to System.Runtime.InteropServices.WindowsRuntime for netstandard2.0 target. ( link ).

This on its own though is not causing any immediate trouble...

The realization

I created a clean project with reference to Rx and tried to await an IObservable... and it worked just fine, so I figured, the issue will be somewhere else... So I started stripping down the dependencies from our original project, until it finally built successfully.

And then I found that because we migrated to .NET Core, we no longer had implicit access to certain Windows specific APIs, so we referenced Microsoft.Windows.Compatibility and by doing that we must have activated a special scenario for Rx's platform services, or something where it started to try to be WinRT compatible and give us those errors when trying to await on an IObservable.

The solution

The solution was to either reference the more specific compatibility packages, like System.Configuration.ConfigurationManager and System.ServiceProcess.ServiceController and/or to explicitly use the ToTask() extension method before attempting to await an IObservable.

The question

With all this, I'm still a little confused about why Rx has reference to WinRT Interop package for its .NET Standard (cross platform) target? I'd guess this weird issue would never have came up in the first place if it wouldn't have that reference.

Repro

csproj file

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Windows.Compatibility" Version="3.0.0" />
    <PackageReference Include="System.Reactive" Version="4.1.6" />
  </ItemGroup>

</Project>

Program.cs

using System;
using System.Reactive.Linq;
using System.Threading.Tasks;

namespace Repro
{
    class Program
    {
        static async Task Main(string[] args)
        {
            await Observable.Return("Hello World");
        }
    }
}
@clairernovotny
Copy link
Member

Does this happen with Rx.NET 4.2?

@petroemil
Copy link
Author

Does this happen with Rx.NET 4.2?

No, it seems to be working now as expected.
Thank you.

@nathanpovo
Copy link

I got this same strange behavior in a WPF project targeting net5.0-windows.

In my case, one of projects I was referencing had the package System.Runtime.WindowsRuntime. After hours of trial and error, I tried removing the package System.Runtime.WindowsRuntime and the build finally worked.

Repro

csproj file

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Reactive" Version="5.0.0" />
    <PackageReference Include="System.Runtime.WindowsRuntime" Version="4.7.0" />
  </ItemGroup>

</Project>

Program.cs

using System;
using System.Reactive.Linq;
using System.Threading.Tasks;

namespace Tester
{
    class Program
    {
        static async Task Main(string[] args)
        {
            await Observable.Return("Hello World");
        }
    }
}

@ndrwrbgs
Copy link

This has indeed recurred with net5.0 CC: @akarnokd

@akarnokd akarnokd reopened this Feb 16, 2022
@SuperJMN
Copy link

This is happening to me in LINQPad 7 x64 using .NET 6 and System.Reactive 5. It doesn't happen with 4.x, though.

image

@vbjay
Copy link

vbjay commented Jul 26, 2022

This is happening to me in LINQPad 7 x64 using .NET 6 and System.Reactive 5. It doesn't happen with 4.x, though.

image

image

@Tim-Utelogy
Copy link

When you do a platform specific TFM like net5.0-windows a lot of build magic happens to autogenerate the WinRT bindings. That magic ultimately conflicts with System.Runtime.WindowsRuntime and you don't need it.

@glopesdev
Copy link

glopesdev commented Dec 4, 2022

Tbh, I think it would be great if all the specific scheduler stuff was removed into a separate assembly/package. No need to go back to having 4 libraries, but at least separating UI and platform specific from the completely agnostic components would make for a much more sane and lean build process.

E.g. it's probably fine to have framework thread and task pool schedulers, etc, but folding in WinRT and WinForms depending on platform target just seems like a very strange design decision.

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

9 participants