Skip to content

Dotnet MSBuild: Get Property does not expand properties #11735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ByronMayne opened this issue Mar 20, 2025 · 7 comments
Open

Dotnet MSBuild: Get Property does not expand properties #11735

ByronMayne opened this issue Mar 20, 2025 · 7 comments
Assignees
Labels
Documentation Issues about docs, including errors and areas we should extend (this repo and learn.microsoft.com) Priority:2 Work that is important, but not critical for the release triaged

Comments

@ByronMayne
Copy link

ByronMayne commented Mar 20, 2025

Describe the bug

Unlike building thee project or uses msbuild properties in launchsettings.json the dotnet cli command dotnet msbuild --getProperty does not expand properties correctly, which returns results that don't match other implementations.

To Reproduce

<Project>
  <ItemGroup>
    <Item Include="1"/>
    <Item Include="2"/>
  </ItemGroup>
  <PropertyGroup>
    <DynamicValue>@(Item)</DynamicValue>  
 </PropertyGroup>
 <Target Name="Print">
    <Message Importance="high" Text="Value: $(DynamicValue)"/>
 </Target>
</Project>

Save that xml as Example.target and run dotnet msbuild Example.target --getProperty:DynamicValue which will return @(Item) instead of the correct 1;2 like building the project or uses launch settings.

If you run dotnet msbuild Example.targe -t:Print you will see it output the correct value of 1;2

Fun Facts

@marcpopMSFT marcpopMSFT transferred this issue from dotnet/sdk Apr 15, 2025
@marcpopMSFT
Copy link
Member

Triage: the getProperty feature is an MSBuild feature. Properties are evaluated before Items so the behavior makes sense even if it's not what you expected. I think if you set the property in a target and then explicitly ran the target when calling getProperty.

I wonder if MSBuild should potentially detect this (ie when it's about to return @ in the getProperty output) and let the customer know how to get this to work.

@ByronMayne
Copy link
Author

Just from the documentation it does not mention that there is a difference, which at least there should be a call out. MSBuild is a beast and it's easy to fall into these little edge cases. Based of the docs it makes it appear like it would be the exact same value as if you are doing a build, which is not the case.

You can get the values that MSBuild items and properties would have without executing a build. This option is helpful when you need these values as inputs for the desired build process, but you need to evaluate a project to get the value. -- docs

@ForNeVeR
Copy link

ForNeVeR commented Apr 16, 2025

In other words, I'd expect --getProperty to get the property value after all evaluation, including properties and items. While I agree that the scenario in question is rather uncommon, let's consider what the use of the property value after substituting of other properties is, but before substituting any items.

The user has a string @(Item), and what are they supposed to do with that? The only thing that comes to mind would be to parse it, then invoke the corresponding --getItem commands to resolve the items in question, and then substitute them manually.

But this is what MSBuild already does! We have this logic! It is just not wired up with the --getProperty mechanism.

@ByronMayne
Copy link
Author

You worded that much better then I would!

@maridematte maridematte added Documentation Issues about docs, including errors and areas we should extend (this repo and learn.microsoft.com) Priority:2 Work that is important, but not critical for the release triaged labels Apr 24, 2025
@rainersigwald
Copy link
Member

Ok, so this is By Design, but very confusing.

In other words, I'd expect --getProperty to get the property value after all evaluation, including properties and items.

That's exactly what we do! The value after evaluation is the string @(Item).

When a task is invoked, we recursively expand:

  1. Value: $(DynamicValue)
  2. Value: @(Item)
  3. Value: 1;2

We have some documentation on this: subtle effects of the evaluation order--and man does that "subtle" deserve emphasis :(

I would not want to do task-invocation-style recursive expansion automatically with -getProperty, because I think the right philosophy is that that should be a wrapper over using the API to evaluate a project and call GetPropertyValue, which would have the described behavior.

I could be convinced about an opt-in mode, though! Getting back an @() isn't super helpful.

The original feature request (#3911) that turned into -getProperty and friends was for -evaluate:{expression}, which might have bypassed this; I would expect -evaluate:$(DynamicValue) to go through the recursive expansion above, if it existed. That plays very badly with multiple returns though.

@rainersigwald
Copy link
Member

@ghogen we should see if we can find a way to make the above behavior clearer in docs.

@ForNeVeR
Copy link

ForNeVeR commented Apr 24, 2025

I would maybe vote for different commands like -getProperty and -getEvaluatedProperty ?

-evaluate: also looks quite nice, to be honest, but I cannot say it's often necessary.

(I do use -getProperty and -getItem in some of my small tools, so these options are quite useful and practical even as they are implemented)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation Issues about docs, including errors and areas we should extend (this repo and learn.microsoft.com) Priority:2 Work that is important, but not critical for the release triaged
Projects
None yet
Development

No branches or pull requests

6 participants