msbuild
msbuild copied to clipboard
[Bug]: Inconsistent behavior of duplicate path separator in property
Issue Description
In another project, I added the following properties at <solution-dir>/props/MyProject.Paths.props (for collecting common directories used throughout project files):
<PropertyGroup>
<RootPath>$(MSBuildThisFileDirectory)\..</RootPath> <!-- Property in question. -->
<ArtifactsPath>$(RootPath)\artifacts</ArtifactsPath>
</PropertyGroup>
I add the extra path separator in RootPath because I find separating $(MSBuildThisFileDirectory) and .. more readable. This, of course, evaluates to <MSBuildThisFileDirectory>\\.., which works for me on the CLI and from Visual Studio, as well as in the project's CI.
However, the maintainer of the project had asked me to change this property to remove the extra path separator because the solution would not build otherwise:
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\<user>\<solution-dir>\props\artifacts\obj\MyProject\debug\MyProject.exe.withSupportedRuntime.config'.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
at System.Xml.XmlTextReaderImpl.FinishInitUriString()
at System.Xml.XmlReaderSettings.CreateReader(String inputUri, XmlParserContext inputContext)
at System.Xml.Linq.XDocument.Load(String uri, LoadOptions options)
at Microsoft.Build.Tasks.GenerateBindingRedirects.LoadAppConfig(ITaskItem appConfigItem)
at Microsoft.Build.Tasks.GenerateBindingRedirects.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() MyProject C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets 2509
You can see here, that MSBuild generates an artifacts directory inside of the props directory. I have to assume this is because $(RootPath) evaluates to an empty string, leaving only \artifacts as the ArtifactsPath property.
Steps to Reproduce
As this does work for both me and the CI, I wouldn't know how to reproduce this.
Expected Behavior
The evaluation of the properties is consistent across machines.
Actual Behavior
It is not.
Perhaps interesting, the below does not work either, not for me, nor for the maintainer:
<RootPath>$([System.IO.Path]::GetDirectoryName($(MSBuildThisFileDirectory)))</RootPath>
Despite the same being used in other dotnet-adjacent repositories: https://github.com/dotnet/java-interop/blob/fcad3368815dffd0f38f64384aa21b0b65367d68/Directory.Build.props#L20-L23.
Analysis
No response
Versions & Configurations
Working:
msbuild --version: MSBuild version 17.11.2+c078802d4 for .NET Framework
17.11.2.32701
dotnet --list-sdks: 9.0.100-preview.7.24407.12
Not working:
msbuild --version: MSBuild version 17.9.8+b34f75857 for .NET Framework
17.9.8.16306
dotnet --list-sdks: 8.0.202