Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing system assembly in .appxupload only

We're developing an UWP LOB app to be published via the Windows Store for Business (build target >= 1607). The UWP application references:

  • Stubble.Core via nuget (targets .NET Standard 1.3) which references
  • System.Reflection.TypeExtensions 4.3.0, which references
  • System.Private.Reflection.Extensibility.dll version 4.0.0.0.

The app will compile and run locally both in debug and release (compiled via .NET native) mode. When uploading the .appxupload to the Windows Store, the resulting app will throw an exception:

System.IO.FileNotFoundException: Could not load file or assembly 'System.Private.Reflection.Extensibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified. File name: 'System.Private.Reflection.Extensibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' at Internal.Reflection.Extensions.NonPortable.PropertyPolicies.GetInheritedMemberInfo(PropertyInfo underlyingMemberInfo, Type reflectedType) at Internal.Reflection.Extensions.NonPortable.MemberEnumerator.d__11.MoveNext() at System.Collections.Generic.LowLevelList1.InsertRange(Int32 index, IEnumerable`1 collection) at System.Reflection.TypeExtensions.GetMembers(Type type, Object nameFilterOrAnyName, BindingFlags bindingAttr) at System.Reflection.TypeExtensions.GetMembers(Type type, BindingFlags bindingAttr) at Stubble.Core.Settings.RendererSettingsDefaults.GetMemberLookup(Type objectType)

I can reproduce this issue when extracting the .appxbundle from the .appxupload and sideloading the package via PowerShell. Note, that the .appxbundle within the .appxupload features .NET assemblies and is therefore not compiled to .NET native.

I figure that the Windows Store is should perform this task, but it actually does not (as you can see from the stack trace above) - maybe due to the fact, that we're utilizing the Desktop Bridge feature for our UWP app.

When searching for the System.Private.Reflection.Extensibility.dll, it seems that this assembly relates to .NET Native and the build chain (as it comes with the .NET Native nuget package and MSBuild).

So my question is: Why does the app fail to load the assembly (but does not in debug/release mode)? Does System.Reflection.TypeExtensions expect the app to be compiled with .NET Native which actually works locally?

I tried:

  • Uploading the .appxbundle compiled with .NET Native (which is not accepted by the store)
  • Referencing different versions of the Microsoft.NETCore.UniversalWindowsPlatform package (which includes the .NET Native packages)
  • Referencing the private library manually (which yields compiler errors because of duplicated assembly references)
  • Upgrading System.Reflection.TypeExtensions to 4.4
  • Created a .wapproj wrapper for deployment (issue remains the same)
  • Added a binding redirect, which causes the app to crash
like image 506
Gene Avatar asked May 07 '18 13:05

Gene


1 Answers

So the problem seems to be caused by the Windows Store not re-compiling the AppX bundle with .NET Native.

If you build an UWP app locally, within ...

  • Debug mode, you will get an AppX bundle with .NET assemblies and a reference to the .NET Core CLR (which works)
  • Release mode, you will get an AppX bundle with a natively compiled application and a reference to the .NET Native runtime (which works as well)

When creating an app package to be submitted to the Windows Store, you will get an AppX bundle with .NET assemblies and a reference to the .NET Native version which should be used by the Windows Store to re-compile the application (determined by the version of the Microsoft.NETCore.UniversalWindowsPlatform nuget package you are using).

For apps with the runFullTrust capability enabled, the Store will not re-compile the application. Therefore, you will distribute an AppX bundle which contains .NET assemblies and relies on the .NET Native runtime (which actually runs remarkably well). As soon as the CLR attempts to load an assembly of the .NET Core implementation, you'll get the error mentioned above. Additionally, your app will be way slower compared to the .NET Native-compiled one.

I guess for a regular AppX bundle with runFullTrust enabled, the Store cannot decide whether to re-compile the app, as such a package could contain other application types (e.g. Windows Forms or WPF).

To overcome this issue, create a "Windows Application Packaging Project" and add the UWP application as a reference. Submit the AppX bundle generated from that project to the store. The Windows Store will then re-compile the .NET assemblies as expected.

For further reference, see Could not load file or assembly 'System.Private.CoreLib...'.

like image 65
Gene Avatar answered Oct 19 '22 23:10

Gene