Skip to content

Conversation

@jonathanpeppers
Copy link
Member

@jonathanpeppers jonathanpeppers commented Dec 5, 2025

Context: https://github.com/dotnet/sdk/blob/49c0d73c0bfa9eb2870827828354d5c96ed786f0/documentation/specs/dotnet-run-for-maui.md
Context: dotnet/android#10631
Context: dotnet/android#10640

Add support for calling the DeployToDevice MSBuild target during dotnet run. The target is invoked after the build step (or with --no-build) to enable deployment to physical devices or emulators.

The main change here is to create the RunCommandSelector earlier in the RunCommand execution, so that it can be used both for selecting the target framework and device before build, and for invoking the DeployToDevice target after build.

I tested this by making DotnetRunDevices.csproj include a target:

<Target Name="DeployToDevice" DependsOnTargets="ResolveFrameworkReferences">
  <Message Text="DeployToDevice: Deployed to device $(Device) with RuntimeIdentifier $(RuntimeIdentifier)" Importance="high" />
</Target>

Where DependsOnTargets="ResolveFrameworkReferences" mimics what can happen in the Android workload.

I had to stop caching each ProjectInstance in RunCommandSelector,
as doing so can cause:

》"artifacts\tmp\Debug\testing\ItDoesNotCall---A078BA19\DotnetRunDevices.csproj" (DeployToDevice target) (1) ->
》(ResolveFrameworkReferences target) ->
》  artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018: The "ResolveFrameworkReferences" task failed unexpectedly.
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018: System.ArgumentException: An item with the same key has already been added. Key: Microsoft.NETCore.App
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Linq.Enumerable.SpanToDictionary[TSource,TKey](ReadOnlySpan`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolveFrameworkReferences.ExecuteCore() in src\Tasks\Microsoft.NET.Build.Tasks\ResolveFrameworkReferences.cs:line 29
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.NET.Build.Tasks.TaskBase.Execute() in src\Tasks\Common\TaskBase.cs:line 36
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(TaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)

The ResolveFrameworkReferences target will add duplicate Microsoft.NETCore.App items within a ProjectInstance causing the exception above.

@jonathanpeppers jonathanpeppers force-pushed the dev/peppers/DeployToDevice branch 2 times, most recently from b05d995 to 09f9f0d Compare December 9, 2025 20:15
jonathanpeppers added a commit to dotnet/android that referenced this pull request Dec 9, 2025
Context: dotnet/sdk#52046
Context: https://github.com/dotnet/sdk/blob/c164a9bc1246c48191fb780992530f0fe975141b/documentation/specs/dotnet-run-for-maui.md

When the `DeployToDevice` target is run by the `dotnet run` pipeline,
we will no longer need to make the `ComputeRunArguments` target deploy
anything.

We are thinking this feature can ship in future .NET 11 and 10.0.200
SDKs.
@jonathanpeppers jonathanpeppers force-pushed the dev/peppers/DeployToDevice branch from 023e459 to cb6877a Compare December 10, 2025 18:56
Context: dotnet/android#10631
Context: dotnet/android#10640

Add support for calling the `DeployToDevice` MSBuild target during
`dotnet run`. The target is invoked after the build step (or with
--no-build) to enable deployment to physical devices or emulators.

The main change here is to create the `RunCommandSelector` earlier in
the `RunCommand` execution, so that it can be used both for selecting
the target framework and device before build, and for invoking the
`DeployToDevice` target after build.

I tested this by making `DotnetRunDevices.csproj` include a target:

    <Target Name="DeployToDevice" DependsOnTargets="ResolveFrameworkReferences">
      <Message Text="DeployToDevice: Deployed to device $(Device) with RuntimeIdentifier $(RuntimeIdentifier)" Importance="high" />
    </Target>

Where `DependsOnTargets="ResolveFrameworkReferences"` mimics what can
happen in the Android workload.

I had to stop caching each `ProjectInstance` in `RunCommandSelector`,
as doing so can cause:

    》"artifacts\tmp\Debug\testing\ItDoesNotCall---A078BA19\DotnetRunDevices.csproj" (DeployToDevice target) (1) ->
    》(ResolveFrameworkReferences target) ->
    》  artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018: The "ResolveFrameworkReferences" task failed unexpectedly.
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018: System.ArgumentException: An item with the same key has already been added. Key: Microsoft.NETCore.App
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Linq.Enumerable.SpanToDictionary[TSource,TKey](ReadOnlySpan`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolveFrameworkReferences.ExecuteCore() in src\Tasks\Microsoft.NET.Build.Tasks\ResolveFrameworkReferences.cs:line 29
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.NET.Build.Tasks.TaskBase.Execute() in src\Tasks\Common\TaskBase.cs:line 36
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(TaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)

The `ResolveFrameworkReferences` target will add duplicate
`Microsoft.NETCore.App` items within a `ProjectInstance` causing the
exception above.
@jonathanpeppers jonathanpeppers force-pushed the dev/peppers/DeployToDevice branch from cb6877a to 3933774 Compare December 11, 2025 22:11
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.

2 participants