diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs
index f2038baae3ef..598d1dfe3483 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs
@@ -30,6 +30,7 @@ public static class Constants
public const string Build = nameof(Build);
public const string ComputeRunArguments = nameof(ComputeRunArguments);
public const string ComputeAvailableDevices = nameof(ComputeAvailableDevices);
+ public const string DeployToDevice = nameof(DeployToDevice);
public const string CoreCompile = nameof(CoreCompile);
// MSBuild item metadata
diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx
index fbb06189dc5e..98e9add2b425 100644
--- a/src/Cli/dotnet/Commands/CliCommandStrings.resx
+++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx
@@ -1717,6 +1717,9 @@ The default is to publish a framework-dependent application.
The build failed. Fix the build errors and run again.
+
+ Deployment to device failed. Fix any deployment errors and run again.
+
The launch profile "{0}" could not be applied.
{1}
diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs
index fb5dffd622f5..a2a54a47d5c5 100644
--- a/src/Cli/dotnet/Commands/Run/RunCommand.cs
+++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs
@@ -157,7 +157,10 @@ public int Execute()
try
{
// Pre-run evaluation: Handle target framework and device selection for project-based scenarios
- if (ProjectFileFullPath is not null && !TrySelectTargetFrameworkAndDeviceIfNeeded(logger))
+ using var selector = ProjectFileFullPath is not null
+ ? new RunCommandSelector(ProjectFileFullPath, Interactive, MSBuildArgs, logger)
+ : null;
+ if (selector is not null && !TrySelectTargetFrameworkAndDeviceIfNeeded(selector))
{
// If --list-devices was specified, this is a successful exit
return ListDevices ? 0 : 1;
@@ -200,6 +203,17 @@ public int Execute()
}
}
+ // Deploy step: Call DeployToDevice target if available
+ // This must run even with --no-build, as the user may have selected a different device
+ if (selector is not null && !selector.TryDeployToDevice())
+ {
+ // Only error if we have a valid project (not a .sln file, etc.)
+ if (selector.HasValidProject)
+ {
+ throw new GracefulException(CliCommandStrings.RunCommandDeployFailed);
+ }
+ }
+
ICommand targetCommand = GetTargetCommand(projectFactory, cachedRunProperties, logger);
ApplyLaunchSettingsProfileToCommand(targetCommand, launchSettings);
@@ -234,12 +248,10 @@ public int Execute()
/// Uses a single RunCommandSelector instance for both operations, re-evaluating
/// the project after framework selection to get the correct device list.
///
- /// Optional logger for MSBuild operations (device selection)
+ /// The RunCommandSelector instance to use for selection
/// True if we can continue, false if we should exit
- private bool TrySelectTargetFrameworkAndDeviceIfNeeded(FacadeLogger? logger)
+ private bool TrySelectTargetFrameworkAndDeviceIfNeeded(RunCommandSelector selector)
{
- Debug.Assert(ProjectFileFullPath is not null);
-
var globalProperties = CommonRunHelpers.GetGlobalPropertiesFromArgs(MSBuildArgs);
// If user specified --device on command line, add it to global properties and MSBuildArgs
@@ -258,13 +270,10 @@ private bool TrySelectTargetFrameworkAndDeviceIfNeeded(FacadeLogger? logger)
if (!ListDevices && hasFramework && hasDevice)
{
- // Both framework and device are pre-specified, no need to create selector or logger
+ // Both framework and device are pre-specified
return true;
}
- // Create a single selector for both framework and device selection
- using var selector = new RunCommandSelector(ProjectFileFullPath, globalProperties, Interactive, MSBuildArgs, logger);
-
// Step 1: Select target framework if needed
if (!selector.TrySelectTargetFramework(out string? selectedFramework))
{
diff --git a/src/Cli/dotnet/Commands/Run/RunCommandSelector.cs b/src/Cli/dotnet/Commands/Run/RunCommandSelector.cs
index f10239673125..73286ec192a8 100644
--- a/src/Cli/dotnet/Commands/Run/RunCommandSelector.cs
+++ b/src/Cli/dotnet/Commands/Run/RunCommandSelector.cs
@@ -31,21 +31,25 @@ internal sealed class RunCommandSelector : IDisposable
private ProjectCollection? _collection;
private Microsoft.Build.Evaluation.Project? _project;
- private ProjectInstance? _projectInstance;
+
+ ///
+ /// Gets whether the selector has a valid project that can be evaluated.
+ /// This is false for .sln files or other invalid project files.
+ ///
+ public bool HasValidProject { get; private set; }
/// Path to the project file to evaluate
- /// Global MSBuild properties to use during evaluation
/// Whether to prompt the user for selections
+ /// MSBuild arguments containing properties and verbosity settings
/// Optional binary logger for MSBuild operations. The logger will not be disposed by this class.
public RunCommandSelector(
string projectFilePath,
- Dictionary globalProperties,
bool isInteractive,
MSBuildArgs msbuildArgs,
FacadeLogger? binaryLogger = null)
{
_projectFilePath = projectFilePath;
- _globalProperties = globalProperties;
+ _globalProperties = CommonRunHelpers.GetGlobalPropertiesFromArgs(msbuildArgs);
_isInteractive = isInteractive;
_msbuildArgs = msbuildArgs;
_binaryLogger = binaryLogger;
@@ -102,9 +106,9 @@ public void InvalidateGlobalProperties(Dictionary updatedPropert
// Dispose existing project to force re-evaluation
_project = null;
- _projectInstance = null;
_collection?.Dispose();
_collection = null;
+ HasValidProject = false;
}
///
@@ -114,8 +118,9 @@ private bool OpenProjectIfNeeded([NotNullWhen(true)] out ProjectInstance? projec
{
if (_project is not null)
{
- Debug.Assert(_projectInstance is not null);
- projectInstance = _projectInstance;
+ // Create a fresh ProjectInstance for each build operation
+ // to avoid accumulating state (existing item groups) from previous builds
+ projectInstance = _project.CreateProjectInstance();
return true;
}
@@ -126,14 +131,15 @@ private bool OpenProjectIfNeeded([NotNullWhen(true)] out ProjectInstance? projec
loggers: GetLoggers(),
toolsetDefinitionLocations: ToolsetDefinitionLocations.Default);
_project = _collection.LoadProject(_projectFilePath);
- _projectInstance = _project.CreateProjectInstance();
- projectInstance = _projectInstance;
+ projectInstance = _project.CreateProjectInstance();
+ HasValidProject = true;
return true;
}
catch (InvalidProjectFileException)
{
// Invalid project file, return false
projectInstance = null;
+ HasValidProject = false;
return false;
}
}
@@ -461,6 +467,36 @@ public bool TrySelectDevice(
}
}
+ ///
+ /// Attempts to deploy to a device by calling the DeployToDevice MSBuild target if it exists.
+ /// This reuses the already-loaded project instance for performance.
+ ///
+ /// True if deployment succeeded or was skipped (no target), false if deployment failed
+ public bool TryDeployToDevice()
+ {
+ if (!OpenProjectIfNeeded(out var projectInstance))
+ {
+ // Invalid project file
+ return false;
+ }
+
+ // Check if the DeployToDevice target exists in the project
+ if (!projectInstance.Targets.ContainsKey(Constants.DeployToDevice))
+ {
+ // Target doesn't exist, skip deploy step
+ return true;
+ }
+
+ // Build the DeployToDevice target
+ var buildResult = projectInstance.Build(
+ targets: [Constants.DeployToDevice],
+ loggers: GetLoggers(),
+ remoteLoggers: null,
+ out _);
+
+ return buildResult;
+ }
+
///
/// Gets the list of loggers to use for MSBuild operations.
/// Creates a fresh console logger each time to avoid disposal issues when calling Build() multiple times.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
index 3805b9b8be5c..136767b262f3 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
@@ -2687,6 +2687,11 @@ Ve výchozím nastavení je publikována aplikace závislá na architektuře.Sestavování...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.Spuštění cíle {0} ke zjištění příkazů spuštění pro tento projekt se nezdařilo. Opravte chyby a upozornění a spusťte je znovu.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
index ffc2aaf9640c..cff5cde37fa5 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
@@ -2687,6 +2687,11 @@ Standardmäßig wird eine Framework-abhängige Anwendung veröffentlicht.Buildvorgang wird ausgeführt...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.Das {0} Ziel ausführen, um zu ermitteln, dass ein Fehler bei den Ausführungsbefehlen für dieses Projekt aufgetreten ist. Beheben Sie die Fehler und Warnungen, und führen Sie dies erneut aus.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
index 0c5d385caff6..c07254581fb4 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
@@ -2687,6 +2687,11 @@ El valor predeterminado es publicar una aplicación dependiente del marco.Compilando...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.Error al ejecutar el destino {0} para detectar comandos de ejecución para este proyecto. Corrija los errores y advertencias y vuelva a ejecutarlo.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
index ad02d5f06a45..4d87622d05d2 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
@@ -2687,6 +2687,11 @@ La valeur par défaut est de publier une application dépendante du framework.
Génération...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.L’exécution de la {0} cible pour découvrir les commandes d’exécution a échoué pour ce projet. Corrigez les erreurs et les avertissements, puis réexécutez.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
index 5bc254561ddf..9339191bf3bf 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
@@ -2687,6 +2687,11 @@ Per impostazione predefinita, viene generato un pacchetto dipendente dal framewo
Compilazione...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.L'esecuzione della destinazione {0} per individuare i comandi di esecuzione non è riuscita per questo progetto. Correggere gli errori e gli avvisi ed eseguire di nuovo.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
index f942b99ce5d8..6b6ed718912e 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
@@ -2687,6 +2687,11 @@ The default is to publish a framework-dependent application.
ビルドしています...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.このプロジェクトで実行コマンドを検出するための {0} ターゲットの実行に失敗しました。エラーと警告を修正して、もう一度実行してください。
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
index 4f008556132d..e9e8dbecd20a 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
@@ -2687,6 +2687,11 @@ The default is to publish a framework-dependent application.
빌드하는 중...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.이 프로젝트에 대해 실행 명령을 검색하기 위해 {0} 대상을 실행하지 못했습니다. 오류 및 경고를 수정하고 다시 실행합니다.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
index 9598de759b77..cf04d65e6d21 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
@@ -2687,6 +2687,11 @@ Domyślnie publikowana jest aplikacja zależna od struktury.
Trwa kompilowanie...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.Uruchomienie obiektu docelowego {0} w celu odnalezienia poleceń przebiegu dla tego projektu nie powiodło się. Usuń błędy i ostrzeżenia, a następnie uruchom ponownie.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
index f92368671030..d8ad620ab52a 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
@@ -2687,6 +2687,11 @@ O padrão é publicar uma aplicação dependente de framework.
Compilando...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.Falha na execução do destino {0} para descobrir comandos de execução para este projeto. Corrija os erros e avisos e execute novamente.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
index b5683e18c60d..1168336d6521 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
@@ -2687,6 +2687,11 @@ The default is to publish a framework-dependent application.
Сборка…
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.Не удалось запустить цель {0} для обнаружения команд выполнения для этого проекта. Исправьте ошибки и предупреждения и повторите попытку.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
index e2aebc3732b3..9e40a55ab8d3 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
@@ -2687,6 +2687,11 @@ Varsayılan durum, çerçeveye bağımlı bir uygulama yayımlamaktır.
Derleniyor...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.Çalıştırma komutlarını bulmak için {0} hedefini çalıştırma bu proje için başarısız oldu. Hataları ve uyarıları düzeltip yeniden çalıştırın.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
index a39b9ae22a1c..32ed189af92d 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
@@ -2687,6 +2687,11 @@ The default is to publish a framework-dependent application.
正在生成...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.为此项目运行 {0} 目标以发现运行命令失败。请修复错误和警告,然后再次运行。
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
index 424c4a1574d8..b6c8a83ad247 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
@@ -2687,6 +2687,11 @@ The default is to publish a framework-dependent application.
正在建置...
+
+ Deployment to device failed. Fix any deployment errors and run again.
+ Deployment to device failed. Fix any deployment errors and run again.
+
+ Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again.執行 {0} 目標以探索對此專案的執行命令失敗。修正錯誤和警告,然後重新執行。
diff --git a/test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj b/test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj
index 1214d95cdf76..04ce32c6db1d 100644
--- a/test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj
+++ b/test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj
@@ -49,4 +49,9 @@
+
+
+
+
+
diff --git a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs
index 77428f8353a9..c2c1948b12a5 100644
--- a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs
+++ b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs
@@ -16,8 +16,6 @@ public GivenDotnetRunSelectsDevice(ITestOutputHelper log) : base(log)
{
}
- string ExpectedRid => OperatingSystem.IsWindows() ? "win" : (OperatingSystem.IsMacOS() ? "osx" : "linux");
-
///
/// Helper method to assert conditions about MSBuild target execution in a binlog file
///
@@ -179,7 +177,7 @@ public void ItAutoSelectsSingleDeviceWithoutPrompting(bool interactive)
// Should auto-select the single device and run successfully
result.Should().Pass()
.And.HaveStdOutContaining("Device: single-device")
- .And.HaveStdOutContaining($"RuntimeIdentifier: {ExpectedRid}");
+ .And.HaveStdOutContaining($"RuntimeIdentifier: {RuntimeInformation.RuntimeIdentifier}");
// Verify the binlog file was created and the ComputeAvailableDevices target ran
File.Exists(binlogPath).Should().BeTrue("the binlog file should be created");
@@ -280,4 +278,102 @@ public void ItPromptsForTargetFrameworkEvenWhenDeviceIsSpecified()
result.Should().Fail()
.And.HaveStdErrContaining("Your project targets multiple frameworks. Specify which framework to run using '--framework'");
}
+
+ [Fact]
+ public void ItCallsDeployToDeviceTargetWhenDeviceIsSpecified()
+ {
+ var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices")
+ .WithSource();
+
+ string deviceId = "test-device-1";
+ string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog");
+
+ var result = new DotnetCommand(Log, "run")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId, "-bl");
+
+ // Should run successfully
+ result.Should().Pass()
+ .And.HaveStdOutContaining($"Device: {deviceId}");
+
+ // Verify the binlog file was created and the DeployToDevice target ran
+ File.Exists(binlogPath).Should().BeTrue("the binlog file should be created");
+ AssertTargetInBinlog(binlogPath, "DeployToDevice",
+ targets => targets.Should().NotBeEmpty("DeployToDevice target should have been executed"));
+ }
+
+ [Fact]
+ public void ItCallsDeployToDeviceTargetEvenWithNoBuild()
+ {
+ var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices")
+ .WithSource();
+
+ string deviceId = "test-device-1";
+ string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog");
+
+ // First build the project with the device so DeviceInfo gets generated
+ // Note: dotnet build doesn't support --device flag, use -p:Device= instead
+ new DotnetCommand(Log, "build")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute("--framework", ToolsetInfo.CurrentTargetFramework, $"-p:Device={deviceId}")
+ .Should().Pass();
+
+ // Now run with --no-build
+ var result = new DotnetCommand(Log, "run")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId, "--no-build", "-bl");
+
+ // Should run successfully
+ result.Should().Pass()
+ .And.HaveStdOutContaining($"Device: {deviceId}");
+
+ // Verify the binlog file was created and the DeployToDevice target ran
+ File.Exists(binlogPath).Should().BeTrue("the binlog file should be created");
+ AssertTargetInBinlog(binlogPath, "DeployToDevice",
+ targets => targets.Should().NotBeEmpty("DeployToDevice target should have been executed even with --no-build"));
+ }
+
+ [Fact]
+ public void ItCallsDeployToDeviceTargetWhenDeviceIsAutoSelected()
+ {
+ var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices")
+ .WithSource();
+
+ string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog");
+
+ // Run with auto-selection of single device
+ var result = new DotnetCommand(Log, "run")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "-p:SingleDevice=true", "-bl");
+
+ // Should run successfully
+ result.Should().Pass()
+ .And.HaveStdOutContaining("Device: single-device");
+
+ // Verify the binlog file was created
+ File.Exists(binlogPath).Should().BeTrue("the binlog file should be created");
+
+ // DeployToDevice target should have been called since a device was selected
+ AssertTargetInBinlog(binlogPath, "DeployToDevice",
+ targets => targets.Should().NotBeEmpty("DeployToDevice target should have been executed when a device is selected"));
+ }
+
+ [Fact]
+ public void ItPassesRuntimeIdentifierToDeployToDeviceTarget()
+ {
+ var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices")
+ .WithSource();
+
+ string deviceId = "test-device-1";
+ string rid = RuntimeInformation.RuntimeIdentifier;
+
+ var result = new DotnetCommand(Log, "run")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId, "--runtime", rid);
+
+ // Should run successfully and show the RuntimeIdentifier in the app output
+ result.Should().Pass()
+ .And.HaveStdOutContaining($"Device: {deviceId}")
+ .And.HaveStdOutContaining($"RuntimeIdentifier: {rid}");
+ }
}