Strange assembly path resolution

Hi,
we have been investigating an issue, where an invalid assembly version appeared in build output and discovered this:

If .elements project contains a reference like this one:
<Reference Include="System.Composition.AttributedModel"/>
Then in our case: elements resolves path

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\devportal\59a59d0c\3d0eb4c1\assembly\dl3\e8fdde2b\8775c8da_663ad901\System.Composition.AttributedModel.dll

to a “Temporary ASP.NET Files” folder, which is absolutely offtopic and contains many assemblies but unrelated with the current build task. Of course the reference itself is invalid. Its not a (.netframework) system assembly and should not be resolved, its a .net 7 assembly or an assembly in a Nuget package. This is a simple simulation case, here happened a total mess in anther dependent project.

After all, ive experimented and tried to force the path via HintPath,

<Reference Include="System.Composition.AttributedModel">
  <HintPath>"C:\Users\tumal\.nuget\packages\system.composition.attributedmodel\1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll"</HintPath>
</Reference>

but result is the same. Resolved path is still Temporary ASP.NET files.

My questions are:
Why elements resolves assemblies from Temporary ASP.NET files ?
Why elements doesnt bother with the hintpath with higher priorty then temp ?
Can i turn it off ?

Thanks.

Sending:
Demo: ClassLibrary5.zip (1.2 KB)
build.log.txt (31.9 KB)

Try building from command line with EBuild and the --debug-reference-resolving switch, which should emit a lot ore details of ALL the places where it looks for dlls, and in which order.

OK, there is a log ebuild.txt (270.3 KB), but i cant see anything what caused 800 attempts to find an assembly in Temporary ASP .NET files, looks like by design. I guess this only makes the resolution slow…

It looks like you have that path set somewhere in one of the AssembnlyFolder(Ex) registry keys. Can you do a fill registry search for “Temporary ASP.NET Files” and see if it pops up in any of those?

Also, where would you expect System.Composition.AttributedModel to be found? it seems it only goes off into the bushes to look for it after it does not find it in the regular places. e.g. compare to how other files ar fine where expected

Checking C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Core.dll, YEP

vs

Checking C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Composition.AttributedModel.dll, NOPE

It does not.

I expect the compiler will throw Unknown Type (System.Composition.Export) error beaces this reference should not be resolved. It has to be a nuget reference.

Well, it could be resolved :wink:

So really, were; chasing a bug that’s a test case error, then? If you change it to am proper NuGet reference, is all ok?

Sorry, i cant send you the original reproduce with more than 300 dlls in the hell.

Okay, bit how did it get there, if these were never valid .dlls that would remove without NuGet?

I’m adding more logging to a new build, to see why/where it goes down into Temporary ASP.NET Files\devportal\59a59d0c\3d0eb4c1\assembly\dl3\e8fdde2b\8775c8da_663ad901.

Update actually, no need to. I know specifically why. the code that changes .NETFramework\v<version> is explicitly told to recurse all subfolders. Now, do I know specifically why? no, because this was written 10-15 years ago. But I’m pretty sure if I drop this, it will fail for others.

Im pretty sure that searching in Temporary ASP.NET Files is not usefull. Framework assemblies in this tree are not for referencing. I was askin, because i was not sure if it is designed or happens due to some of our specifics. I believe this is just a time burner.

Indeed, bit its searching “C:\Windows\Microsoft.NET\Framework64\v4.0.30319” recursively (that part is necessary), and there’s nothing special about “Temporary ASP.NET Files” vs other sub-folders, so it gets searched like all others.

Also since the whole issue only arises because you have bad references to begin with, I fail to see how this is this bad an issue. If I “fixed” this, all these 300+ references you mention would fail anyways, and you’d have to adjust them to correctly be NuGet references…

Yes, but assembly resolution must by precisely done, versions/builds are important. In our case, there is no 300 hundred wrong references. There is 300 netframework / netstandard /net assemblies which refer other specific version on System.Composition.AttributedModel and others. Presence of one elements projects, with wrong reference in dependency chain affects the whole process.

It it will not use Temp:

  1. it will tell the developer that he did it wrong immediately.
  2. It might be a reason why resolving references is sometimes super slow and sometimes OK which we also observe but its hard to reporduce.

On top of that. I think thath the directory tree "C:\Windows\Microsoft.NET" is not good for assembly reference resolution at all. There are runtime assemblies. The right folder should be: %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework.NETFramework only.
But im not expert here.

It checks in both.

And there’s a reason it does check in both / falls back to C:\Windows\Microsoft.NET, if the other doesn’t work. I didn’t just pull EBuild assembly resolution out of my nose one night after having too much to drink :wink:. This is fine-tuned over years based on many different scenarios, and doesn’t do anything “just for fun” that wasn’t added because it was needed for a certain scenario.

Assembly Resolution (for .NET) is a mess, yes. Mostly because, well, when has Microsoft ever designed something that’s not. But it’s a necessary mess.

But believe me, it’s cleaner in EBuild than it is in MSBuild (which, for just one example, will just completely not tell if you if it can’t find an assembly at all, and then let you wonder why you get “unknown identifiers” all offer the place, for stuff that you’re sure you’ve referenced).

Please, you take it too much personal i think. Ive started this as a question, i dont need you to change a think. It is as it is wit all pros and cons and it cant be turned off. We can live with that, even if i dont agree with you.

No worries. My apologies if it came across as such, that was not my intention.

I’m merely trying to explain that its complex, and a bit of a house of cards (build on sand that we don’t move ourselves ;).

What I can try to do for you is specifically exclude “Temporary ASP.NET Files” as a hardcoded name from the “check all sub-folders” recursion code… and wait and see if that breaks things for anyone else.

Up in Personal Downloads; pls let me know if this helps.

Thanks for the effort, the resference resolution looks better. There is a 800 less file existence checks at the result is E: Reference 'System.Composition.AttributedModel' could not be resolved for target 'Echoes' (Echoes .NET anycpu). Which is proper result. No other problems appeared during the resolution here, but we could not complete testing becase of compilation errors in almost every project. Looks like another unrelated bug ?

Error		(E0) Internal error: System.NullReferenceException: Object reference not set to an instance of an object.
   at RemObjects.Elements.Code.Compiler.Compiler.get_DefaultUsesPrefixes()
   at RemObjects.Elements.Code.Compiler.Compiler.a(IHolderOfUses a, MyImmutableDictionary`2& b, Int32& c, String d, IPosition e, Boolean f)
   at RemObjects.Elements.Code.Compiler.Compiler.a(IHolderOfUses a, MyImmutableDictionary`2& b, Int32& c, Uses d, MyImmutableDictionary`2 e)
   at RemObjects.Elements.Code.Compiler.Compiler.ResolveUsesFor(Boolean aEverything)
   at RemObjects.Elements.Code.Compiler.Compiler.ResolveUsesFor(CodeFile aCodeFile, Boolean aEverything)
   at RemObjects.Elements.Code.Compiler.Compiler.ResolveUsesFor(CSharpNamespace aCodeFile, Boolean aEverything)
   at RemObjects.Elements.Code.Compiler.Compiler.GetNamespaceInfo(IHolderOfUses aUses, Boolean aEverything)
   at RemObjects.Elements.Code.Compiler.ResolveTypesCompiler.a(Compiler a, ITypeResolutionScope b, ResolveNamedFlags c, Int32 d, Identifier e, Identifier f, String g, BaseType h, Action`2 i, TypeReference j)
   at RemObjects.Elements.Code.Compiler.ResolveTypeVisitorCompiler.IntResolve__$mapped______(Compiler self, ITypeResolutionScope aScope, NamedTypeReference aType, ResolveNamedFlags aFlags)
   at RemObjects.Elements.Code.Compiler.ResolveTypesCompiler.ResolveType__$mapped______(Compiler self, ITypeResolutionScope aScope, TypeReference aTR, ResolveNamedFlags aFlags)
   at RemObjects.Elements.Code.AttributeImplementation.get_AttributeType()
   at RemObjects.Elements.Code.Compiler.Compiler.CheckAttributes(ITypeResolutionScope aScope, AttributeTargets at, MyImmutableArray`1 aAtt, Action`1 aRemove, MyImmutableArray`1 aXML, IBaseInfo aTarget, Boolean aSkipXML)
   at RemObjects.Elements.Code.Compiler.ResolveMembersCompiler.ResolveMembers__$mapped(Compiler self)
   at RemObjects.Elements.Code.Compiler.Compiler.Compile()	Sys_jadro.SQL		0

It does, yeah, although not one I see here (but changes were made to DefaultUsesPrefixes before and, i believe, after 2869 built, so maybe that’s already fixed… Does this happen in any project, or only a specific one?

Cool.

In 2 of 6 ive tested. Both are C#/Oxygene mixed. Others are pure oxygene.