maui
maui copied to clipboard
Assembly load error in Android app referencing another project referencing a DLL assembly
Description
If a MAUI Android project has a reference to a .NET Standard project in the same solution; and the .NET Standard project has a reference to a .NET Standard assembly, calling a code that eventually calls a code in the assembly fails to load the assembly.
Steps to Reproduce
- Create a new MAUI solution and project.
- Add a .NET Standard project to the solution.
- Add a .NET Standard assembly reference to this project created in Step 2.
- Add a method to the .NET Standard project (created in Step 2) that calls something in the referenced (in Step 3) assembly.
- Add a project reference to the MAUI app that was created in Step 1 that references to the project created in Step 2.
- Call the method that was created in step 4.
i.e. The reference chain: MAUI csproj --> .NET Std. csproj --> .NET Std. DLL
Link to public reproduction project repository
https://github.com/ist-22/10154-repro app has a project reference to lib1 lib1 has an assembly reference to lib2 (so lib2 needs to be compiled first)
Version with bug
6.0.400
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
Android 11
Did you find any workaround?
Add the .NET Standard assembly reference also to the MAUI app project. In the repository uncomment lines 14..18 in app/app.csproj -- this adds an assembly reference to lib2 in app
Relevant log output
No response
Hi @ist-22. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md
This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
Are you sure this is a MAUI (The UI Framework) issue, or an issue with whatever device you're trying to target? Did you try doing this with a dotnet new android
app?
I don't think it's a device/target issue (if this implies architecture) since adding a reference to the assembly in the top MAUI app can act as a workaround.
However, you are right about the MAUI/UI framework question and pointing to the Android project. Yes the issue happens in a project created with dotnet new android
, too; so I guess it's not MAUI specific and maybe more related to Xamarin.Android?
Could you please attach a project that exhibits this scenario?
Hi @ist-22. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md
This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
@jonpryor -- Updated the issue description with the repo link
@jonpryor @jonathanpeppers thoughts?
Does this problem go away if you use net6.0
class libraries (with no platform, vanilla net6.0
) instead of netstandard
?
I have same issue with dynamic assembly loading..
Does this problem go away if you use
net6.0
class libraries (with no platform, vanillanet6.0
) instead ofnetstandard
?
@jonathanpeppers No, still happens.
Can you update the repro? https://github.com/ist-22/10154-repro
Hi @ist-22. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
@jonathanpeppers -- repro updated.
Should we move this to the Android repo? Does this happen with iOS or Windows? Or even a plain old net7.0 console app?
It doesn't happen with a Windows or console app -- can't test iOS.
In VS Windows, the above repro doesn't even build for me, unless I change lib1.csproj
:
<Reference Include="lib2">
<HintPath>..\lib2\bin\$(Configuration)\net7.0\lib2.dll</HintPath>
</Reference>
To this instead:
<ItemGroup>
<ProjectReference Include="..\lib2\lib2.csproj" />
</ItemGroup>
If you have a <Reference/>
to a random .dll
file, the .NET SDK does not go "locate" this file and bring it to the top-level project (application project). I would use <ProjectReference>
instead of <Reference>
in this case, as the .NET SDK supports this. I suspect you'd have the same issue build a .NET 7 self-contained console app -- mobile apps are always self-contained.
If you are hitting this situation with a NuGet package, we can make suggestions on what to do there. Let me know, thanks!
@jonathanpeppers The scenario in this issue is about a case where the user doesn't have access to the source code of the external library (i.e. lib2 in the repro), so adding a project reference is really not an option.
I guess your build failed since lib2 hadn't been built first (this was in the original message but sorry if it wasn't clear enough). The source code of lib2 in the repro is not very relevant to the issue itself and it is only there so that someone who runs the repro doesn't have to call a random DLL.
As I mentioned, this problem doesn't happen with a Windows or console app, also (as long as lib2 has been compiled) IntelliSense is also fine. In all cases (Windows, console and even Android) lib2.dll is copied into bin so I suspect it somehow is not packed into the APK properly.
@ist-22 does the same problem happen in a console app? You would publish it such as dotnet publish --self-contained -r win-x64
, for example, and I bet that lib2.dll
won't be in the build output. You would get a crash at runtime that the assembly isn't found. There isn't any logic in the .NET SDK that loads assemblies and automatically finds references.
So your options are:
- Make a NuGet package, and put
lib2.dll
alongsidelib1.dll
. - Reference
lib2.dll
from the application project.
Does that make sense? Let me know if I missed something here.
Here is another case we saw the same behavior in the .NET SDK: https://github.com/dotnet/maui/issues/11364#issuecomment-1322605802
@jonathanpeppers it does not happen in a console or Windows app, and lib2.dll
is always (even in Android) in the build output. What I can't verify (and suspect where the problem) is that whether it is packed into the APK or not.
Also:
- If I run
dotnet publish --self-contained -r win-x64
I can still seelib2.dll
underwin-x64\publish
and it doesn't crash when run, - Separately, the scenario works fine in a Xamarin.Forms project (i.e. no crash/assembly error).
I appreciate the options/workarounds (I believe the second one is what I suggested as a workaround in my original message) but considering that it works fine with other project types, it makes me think that the expected behaviour is that assembly references inside referenced projects should be OK.
Can you share the console app you made? Is it on a branch of the original repro? Thanks.
Repro updated; cmd
is the new console app project. Reference chain is: cmd
-- (proj. ref.) --> lib1
-- (bin. ref.) --> lib2
.
If you run below, lib2
is copied into cmd
's publish output.
dotnet build lib2
dotnet publish cmd --self-contained -r win-x64
Ok, I tracked this down to:
https://github.com/dotnet/msbuild/blob/a2490dd3f78cce4abc8f9e6f1b5268437332818f/src/Tasks/Microsoft.Common.CurrentVersion.targets#L2322
In the console app we see:
But in the Android app we see:
Putting this in app.csproj
(main Android app) also works around the issue:
<PropertyGroup>
<_ResolveReferenceDependencies>true</_ResolveReferenceDependencies>
</PropertyGroup>
Still figuring out what these settings are for, and how we can fix this.
It appears we need this change in Microsoft.Android.Sdk.AssemblyResolution.targets
:
<Target Name="_ComputeFilesToPublishForRuntimeIdentifiers"
- DependsOnTargets="_FixupIntermediateAssembly;ResolveReferences;ComputeFilesToPublish;$(_RunAotMaybe)"
+ DependsOnTargets="BuildOnlySettings;_FixupIntermediateAssembly;ResolveReferences;ComputeFilesToPublish;$(_RunAotMaybe)"
Returns="@(ResolvedFileToPublish)">
The BuildOnlySettings
target sets $(BuildingProject)
to true
, preventing $(_FindDependencies)
from being set to false
.
I need to write a regression test for this, but will have a PR shortly.
The first attempt to fix this in xamarin/xamarin-android/main didn't work out. (It caused a different issue) Reopening to look into this further.