dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.04k stars 1.16k forks source link

MSBuildProjectExtensionsPath not handled correctly in GenerateTemporaryTargetAssembly #9524

Open BFS-blickshift opened 1 month ago

BFS-blickshift commented 1 month ago

Description

This is a duplicate/regression of #5679, which I cannot reopen.

Using MSBuildProjectExtensionsPath in a dotnet-wpf application results in an error, because the build process tries to access a directory that does not exist and is not the one given in MSBuildProjectExtensionsPath.

Reproduction Steps

Create Directory.Build.props.

<Project>
    <PropertyGroup>
        <BaseOutputPath>$(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\</BaseOutputPath>
        <MSBuildProjectExtensionsPath>$(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\</MSBuildProjectExtensionsPath>
        <IntermediateOutputPath>$(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\$(Configuration)\</IntermediateOutputPath>
    </PropertyGroup>
</Project>

then execute dotnet new wpf -n MyApp ; dotnet new sln ; dotnet sln add MyApp ; dotnet build

Expected behavior

Successful build.

Actual behavior

C:\Program Files\dotnet\sdk\8.0.303\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(266,5): error NETSDK1004: Assets file 'D:\dev\sdktest\obj\MyApp_32u0chsa_wpftmp\project.assets.json' not found. Run a NuGet package restore to generate this file. [D:\dev\sdktest\MyApp\MyApp_32u0chsa_wpftmp.csproj]

Regression?

This seems to be a regression. The original issue #5679 was reported for .NET Core Version: 6.0.100, and was reported as fixed in 7.0.100-preview.4.22252.9. However, I am experiencing this issue with 8.0.303.

Known Workarounds

Everything works as long as MSBuildProjectExtensionsPath is not set. This issue only appears if MSBuildProjectExtensionPath is set.

Impact

The bug impacts any project that uses wpf and sets MSBuildProjectExtensionsPath on .net8.0-windows

Configuration

dotnet --info
.NET SDK:
 Version:           8.0.303
 Commit:            29ab8e3268
 Workload version:  8.0.300-manifests.34944930
 MSBuild version:   17.10.4+10fbfbf2e

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.303\

Other information

No response

lindexi commented 1 month ago

Cc @pchaurasia14

And I can repro this issues in 9.0.0-preview.5.24306.7

Kuldeep-MS commented 4 weeks ago

@BFS-blickshift - I've examined the issue, and it appears that the issue is actually by design. During the WPF build process, a temporary project is generated as part of the markup compilation. During this time, the $(MSBuildProjectName) variable correctly points to the *_wpftmp project name. I attempted to use the $(AssemblyName) variable instead, but it seems that $(AssemblyName) is resolved at a later stage in the build process, which prevents it from being used effectively in this context.

Could you please let me know if the workaround that was shared by the community - here is not working for you?

BFS-blickshift commented 3 weeks ago

If this is "by design" then the design is flawed. The documentation for $(MSBuildProjectName) does not mention anywhere that it can be an arbitrary name. Before I filed this issue I spent many hours trying to resolve the build problems I have in my real solution. I read through issues such as this because it is not possible to set MSBuildProjectExtensionsPath in the project file itself. Using the Directory.build.props seemed to be the recommended workaround for this issue, and now I'm supposed to use a workaround for a workaround that involves using regular expressions and hardcoded project names? This workaround may well work in the case of the minimum reproducible project for this bug report, but the fact that the project name is hardcoded into it makes it unviable for a real solution with dozens of projects - and even if it was, it would still be an unacceptable way of dealing with such a simple task as not polluting your source directory with intermediate and binary files.