Skip to content

dotnet run -e FOO=BAR passes @(RuntimeEnvironmentVariable)#52664

Merged
jonathanpeppers merged 12 commits intorelease/10.0.3xxfrom
dev/peppers/dotnet-run-env
Feb 4, 2026
Merged

dotnet run -e FOO=BAR passes @(RuntimeEnvironmentVariable)#52664
jonathanpeppers merged 12 commits intorelease/10.0.3xxfrom
dev/peppers/dotnet-run-env

Conversation

@jonathanpeppers
Copy link
Member

@jonathanpeppers jonathanpeppers commented Jan 23, 2026

Context: #52492

In investigating how to pass implement dotnet-watch for mobile, we found that we need to make use of:

dotnet run -e FOO=BAR

Where FOO=BAR is passed as an MSBuild item @(RuntimeEnvironmentVariable) to the build, DeployToDevice target, and ComputeRunArguments target:

<ItemGroup>
  <RuntimeEnvironmentVariable Include="FOO" Value="BAR" />
</ItemGroup>

This is straightforward for the in-process MSBuild target invocations, but for the build step, we need to generate a temporary .props file and import using $(CustomBeforeMicrosoftCommonProps).

You will have to opt into this behavior by setting <ProjectCapability Include="RuntimeEnvironmentVariableSupport" /> in your project. The iOS and Android workloads would automatically set this capability.

In the iOS & Android workloads, we would handle processing the @(RuntimeEnvironmentVariable) item to pass the environment variables to the device/emulator when deploying and running the app.

I added a test to verify environment variables are passed through correctly to all targets.

Context: #52492

In investigating how to pass implement `dotnet-watch` for mobile, we
found that we need to make use of:

    dotnet run -e FOO=BAR

Where `FOO=BAR` is passed as an MSBuild item
`@(RuntimeEnvironmentVariable)` to the build, `DeployToDevice` target,
and `ComputeRunArguments` target:

    <ItemGroup>
      <RuntimeEnvironmentVariable Include="FOO" Value="BAR" />
    </ItemGroup>

This is straightforward for the in-process MSBuild target invocations,
but for the build step, we need to generate a temporary `.props`
file and import using `$(CustomBeforeMicrosoftCommonProps)`.

In the iOS & Android workloads, we would handle processing the
`@(RuntimeEnvironmentVariable)` item to pass the environment variables
to the device/emulator when deploying and running the app.

I added a test to verify environment variables are passed through
correctly to all targets.
Updated the props file path generation to use Path.GetFullPath, ensuring that MSBuild receives an absolute path for the generated props file. This improves reliability when referencing the file in build processes.
Replaces backslashes with the system's directory separator in intermediateOutputPath to ensure consistent path handling across platforms. This prevents issues when MSBuild returns paths with Windows-style separators on non-Windows systems.
@jonathanpeppers jonathanpeppers marked this pull request as ready for review February 2, 2026 17:59
@jonathanpeppers jonathanpeppers requested review from baronfel, Copilot and rolfbjarne and removed request for Copilot February 2, 2026 17:59
@jonathanpeppers jonathanpeppers requested a review from tmat February 2, 2026 18:00
// directly to ProjectInstance for in-process target invocations.
var additionalProperties = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>
{
[Constants.CustomBeforeMicrosoftCommonProps] = propsFilePath
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little worried about this negatively impacting existing build processes - but I don't really have a way to validate how widely used this is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick search around github shows ~250 instances, but none really appear foundational and some are in unrelated tooling. I'd expect large 1P customers to have some kind of use of this though, because they use all of the weird extensiblity points. I suppose if MSbuild ever makes a first-class way of injecting Items we could move to that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a spot I didn't like either, here is a GitHub search:

We could introduce a new property?

I really wanted to avoid creating a temp .props file but saw no other way

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine to get in for the first revision and revisit. If we did a new property we'd need to add 'massaging' of that property into Items, and that can also be an error-prone activity due to weird user inputs.

Copilot AI review requested due to automatic review settings February 2, 2026 20:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for passing environment variables from dotnet run -e to MSBuild targets as @(RuntimeEnvironmentVariable) items. Projects opt in to this feature by declaring the RuntimeEnvironmentVariableSupport project capability.

Changes:

  • Environment variables from -e flags are converted to MSBuild items and passed to build, deploy, and ComputeRunArguments targets
  • Opt-in mechanism using project capabilities to avoid impacting projects that don't need this feature
  • Temporary .props file generation for out-of-process build steps

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs Added tests to verify environment variables are passed to targets when opted in, and not passed when opt-out
test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj Test project updated to opt in to capability and log environment variables in targets for verification
src/Cli/dotnet/Commands/Run/RunCommandSelector.cs Added properties to check opt-in capability and retrieve IntermediateOutputPath for props file creation
src/Cli/dotnet/Commands/Run/RunCommand.cs Modified to pass environment variables to selector, create props file for build, and add items for in-process targets
src/Cli/dotnet/Commands/Run/EnvironmentVariablesToMSBuild.cs New utility class for converting environment variables to MSBuild items and managing temporary props files
src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs Added constants for RuntimeEnvironmentVariable items, ProjectCapability, and related properties
documentation/specs/dotnet-run-for-maui.md Documentation explaining the opt-in mechanism and implementation details

@jonathanpeppers jonathanpeppers merged commit bd5d3af into release/10.0.3xx Feb 4, 2026
26 checks passed
@jonathanpeppers jonathanpeppers deleted the dev/peppers/dotnet-run-env branch February 4, 2026 15:04
rolfbjarne added a commit to dotnet/macios that referenced this pull request Mar 4, 2026
Add support for the '@(RuntimeEnvironmentVariable)' item group, which is set when using 'dotnet run' and passing environment variables using '-e|--environment NAME=VALUE' to 'dotnet run'.

This required adding the 'RuntimeEnvironmentVariableSupport' capability to tell 'dotnet run' that we support this.

References:

* dotnet/android#10770
* dotnet/sdk#52664
rolfbjarne added a commit to dotnet/macios that referenced this pull request Mar 9, 2026
Add support for the '@(RuntimeEnvironmentVariable)' item group, which is set when using 'dotnet run' and passing environment variables using '-e|--environment NAME=VALUE' to 'dotnet run'.

This required adding the 'RuntimeEnvironmentVariableSupport' capability to tell 'dotnet run' that we support this.

References:

* dotnet/android#10770
* dotnet/sdk#52664

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants