Missing system assembly in .appxupload only - c#

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

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...'.

Related

Could not load dll from GAC in .NetCore Application

My sample console application (say App1) developed using .Net Core 3.1 and it calls another .NetCore dll (Say Dll1). I have added as reference dll with "Copy Local = Yes". I am using Visual Studio 2019 as Dev environment.
It works fine in direct scenario. Means, when I set "Copy Local = Yes" in App1.
I have registered that .Net Core dll (Dll1) in GAC and set "Copy Local = No" in App1.
Now I could not load .Net Core (Dll1) and it throws below exception.
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'xxxxx, Version=1.0.0.0, Culture=neutral, PublicKeyToken=66f432805192946d'. The system cannot find the file specified.
File name: 'xxxxx, Version=1.0.0.0, Culture=neutral, PublicKeyToken=66f432805192946d'
at xxxxx.Program.Main(String[] args)
My doubts:
Whether .Net Core supports calling dll from GAC?
Kindly help me to resolve this issue.
Regards,
Hari
Your Question
Does .Net Core load assemblies from the Global Assembly Cache (GAC)?
The Short Answer:
Nope
The Long Answer:
When you use an assembly, with CopyLocal = false set, it means that the Assembly (.dll file) will not be placed into the output directory of whatever you just built.
Here, .Net Core acts differently than .Net Framework:
In .Net Framework
As soon as the missing assembly is used somewhere in your executing code, the runtime environment will try to search for it, find and load it. For .Net Framework, this happens in a very specific way, which includes loading it from the GAC (Global Assembly Cache) when available.
And this is how dotnetcore does:
Those dotnetcore apps are designed to be standalones and easy to handle, and do not want to rely on their environment. You deliver all they need to know along with them. So, those apps won't go searching around for missing dlls, and they will not look into the GAC. This is the normal deployment method, and this is called "self contained deployment"
There is, however, something called the runtime package store, that can help optimizing your deployment, by defining that your .Net Core Application is not "self containing", but is deployed against a defined "framework (= where a set of libraries are defined to be present). This is called "framework dependent deployment"
If you need more Information of Framework-Dependent Deployment of .Net Core Apps
Have a look at this
Is there any GAC equivalent for .NET Core?

Display my .NET Standard assembly in the Add Reference dialog for a UWP application

I am trying to figure out how to display my .NET Standard assembly in the Visual Studio Reference Manager under Assemblies/Extensions for a UWP application.
I currently do this with a .NET Framework assembly for .NET Framework applications by setting the proper registry key (from the Microsoft docs article):
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\\AssemblyFoldersEx\MyAssemblies]#=""
This works great for .NET Framework, but I cannot figure out how to do the same thing for my .NET Standard 2.0 assembly and UWP applications.
For example, with the above registry addition and a .NET Framework project, my .NET Framework assembly is automatically shown in the Reference Manager dialog under Assemblies/Extensions. In addition, projects that have a reference to the assembly know where it is located.
I can't seem to do this with a .NET Standard 2.0 assembly and a UWP project. The registry entry appears to be only for .NET Framework assemblies, not assemblies used with UWP. Part of the registry key is the lowest version of the .NET Framework my assembly supports. For example:
HKEY_LOCAL_MACHINE\Software\Microsoft.NETFramework\v2.0.50727\AssemblyFoldersEx\My Assembly\
I tried creating a registry key with the .NET Framework version 4.6.1 and my .NET Standard assembly does show up in the Reference Manager for projects targeting .NET Framework 4.6.1 or newer, but it still does not show up in Reference Manager for UWP projects. I have to manually browse to the assembly file.
Is there a way to have the .NET Standard 2.0 assembly automatically show in Reference Manager for UWP projects like I am able to do for the .NET Framework assembly?
.NET Standard 2.0 assemblies should appear by default as long as your app has a minimum target of 1709 (build 16299 aka "RS3") or higher (source).
If your min-version is lower than that, you can only use .NET Standard 1.4 (source).
I reached out on GitHub as Peter suggested, and I'm including the answer below.
Adding references using that registry key will only work on .NET
Framework. UWP works more like .NET Core, and the runtime won't really
even find the assemblies if they are not properly located either in
the application folder, or in a location specified in the deps.json
file that gets generated as part of the build.
Furthermore, a .NET Standard assembly might have different
dependencies depending on which consuming app is trying to reference
it (for example, you may get different dependencies if you try to load
it from a .NET Core executable than if you are trying to load it from
a .NET Framework executable, or UWP one). For these reasons, the
suggested way to add a reference to a .NET Standard library from a UWP
app is to either add a Project to Project reference, or to depend on
it via a NuGet Package. This will ensure that the right dependencies
get deployed along with your UWP app.

Consuming netstandard13 packages from Xamarin projects

I'm trying to make Npgsql, the PostgreSQL provider for .NET, available for consumption by Xamarin users. Npgsql already supports the .NET Platform Standard (version 3), and the documentation on the standard contains the following sentence:
If a library targets .NET Platform Standard version 1.3, it can only run on .NET Framework 4.6 or later, .NET Core, Universal Windows Platform 10 (UWP), and Mono/Xamarin platforms.
I can successfully install the Npgsql nuget from my Xamarin.Android project. However, when I try to build I get the following error:
System.IO.FileNotFoundException: Could not load assembly 'System.Security.Cryptography.Algorithms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Perhaps it doesn't exist in the Mono for Android profile?
Now, that packages (like many RC2 packages Npgsql depends on) has a lib/MonoAndroid10 directory containing . (also the same in ref), which seems to indicate that the package is supported on Mono.Android, but no DLL is necessary (since the logic is part of the framework). That's great, but the Xamarin.Android build process includes a ResolveAssemblies task, which walks the DLL dependency graph (this is the relevant code). Since Npgsql's netstandard13 DLL references System.Security.Cryptography.Algorthims.dll, this fails.
I'm confused that the nuget declares "it's all good", while the build process itself seems obviously incompatible with consuming netstandard13 dependencies.
Any ideas?

'Oracle.DataAccess' assembly not load

I already installed odac in my pc.I installed visual studio 2012.ORACLE.Data.Access dll available in my refrence.but i am getting following error
Could not load file or assembly 'Oracle.DataAccess' or one of its dependencies. An attempt was made to load a program with an incorrect format.
How can i get rid of this problem.I am running this app locally
The important part of the error message is An attempt was made to load a program with an incorrect format. This is caused by one of two problems:
The Oracle.DataAccess.dll file is compiled in 32 bit and your application is compiling to 64 bit
The Oracle.DataAccess.dll file is compiled in 64 bit and your application is compiling to 32 bit
To fix this, change the CPU Architecture target of your application to x86 if the DLL is 32 bit, or x64 if the DLL is 64 bit.
From the Microsoft documentation for System.BadFormatException:
This exception is thrown when the file format of a dynamic link library (.dll file) or an executable (.exe file) doesn’t conform to the format that the common language runtime expects. In particular, the exception is thrown under the following conditions:
An earlier version of a .NET Framework utility, such as ILDasm.exe or installutil.exe, is used with an assembly that was developed with a later version of the .NET Framework.
To address this exception, use the version of the tool that corresponds to the version of the .NET Framework that was used to develop the assembly. This may require modifying the Path environment variable or providing a fully qualified path to the correct executable.
You try to load an unmanaged dynamic link library or executable (such as a Windows system DLL) as if it were a .NET Framework assembly. The following example illustrates this by using the Assembly.LoadFile method to load Kernel32.dll.
A DLL or executable is loaded as a 64-bit assembly, but it contains 32-bit features or resources. For example, it relies on COM interop or calls methods in a 32-bit dynamic link library.
To address this exception, set the project's Platform target property to x86 (instead of x64 or AnyCPU) and recompile.
Your application’s components were created using different versions of the .NET Framework. Typically, this exception occurs when an application or component that was developed using the .NET Framework 1.0 or the .NET Framework 1.1 tries to load an assembly that was developed using the .NET Framework 2.0 SP1 or later, or when an application that was developed using the .NET Framework 2.0 SP1 or .NET Framework 3.5 tries to load an assembly that was developed using the .NET Framework 4 or later. The BadImageFormatException may be reported as a compile-time error, or the exception may be thrown at run time. The following example defines a StringLib class that has a single member, ToProperCase, and that resides in an assembly named StringLib.dll.
Specifically, item #3 is the root cause of your problem.

critical runtime error after upgrading application with .NET assembly dependencies

I am upgrading an application and running into some issues with it.
Now the old application was version 1.0 and loading a depedency assembly A at version 2.1.1 The assembly is present in application local directory.
I am upgrading the new application to version 2.0 that will load assembly A version 1.0.1 which is present in its application local directory. I've checked application references using ISpy and confirmed the new application references A version 1.0.1
But when I start the new application (v 2.0), it is still trying to load assembly version 2.1.1 and failing. I checked the app.config, machine.config and GAC and there is no redirection for version of assembly A. I also checked fusion log files but don't see any redirection. All I see is the fusion log is that application prebinds A at version 2.1.1 and hence fails to set up the assembly present in its local directory.
Is there something I am missing here? What could be the possible reasons for application still referencing the older assembly at runtime?
Update: Using some tools, I realized the the older assembly is being referenced from a native DLL that is referenced by my application, but I don't know which third party DLL is that, and the application loads a ton of them. The fusion log confirms it by logging "Calling assembly : (Unknown)." for the missing assembly.
Now my next step is to find which dll is referencing the wrong assembly and fix that. Now the problem is that ILSpy tool doesn't show the native DLLs references, and DLLDepends tool does not show the assemblies references, so I am not able to link the two.
thanks
Since the library your trying to reference is supposed to be apart of the GAC; you may want to try:
Control Panel
Small Icons(Administrative Tools)
Event Viewer
Application
Windows itself should throw an exception with some particular details it's attempting to reference when it has an error. Especially if it's apart of the GAC. It was more helpful for me to hone in mscoree.dll and mscorelib.dll libraries fairly easy. Granted those clients that I used that for had corrupt framework; but Event Viewer told me the exact library that it had an issue with.
You may want to try that. Not sure which library; but keep in mind this is usually beneficial to libraries that are found within the %windir%/Assembly folder. Hope that helps.

Categories