Skip to content

Commit 78e9e88

Browse files
WIP working end-to-end
1 parent 09f9f0d commit 78e9e88

File tree

2 files changed

+33
-25
lines changed

2 files changed

+33
-25
lines changed

src/Cli/dotnet/Commands/Run/RunCommand.cs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -149,20 +149,15 @@ public int Execute()
149149
? LoggerUtility.DetermineBinlogger([.. MSBuildArgs.OtherMSBuildArgs], "dotnet-run")
150150
: null;
151151

152-
// Create selector for project-based runs to handle framework/device selection and deploy
153-
using var selector = ProjectFileFullPath is not null
154-
? new RunCommandSelector(
155-
ProjectFileFullPath,
156-
MSBuildArgs,
157-
Interactive,
158-
logger)
159-
: null;
160-
161152
try
162153
{
163154
// Pre-run evaluation: Handle target framework and device selection for project-based scenarios
164-
if (selector is not null && !TrySelectTargetFrameworkAndDeviceIfNeeded(selector))
155+
// This must happen before build so the selected framework/device are used during build
156+
// The method will run restore first (if needed) then create and return a selector
157+
RunCommandSelector? selector = null;
158+
if (ProjectFileFullPath is not null && !TrySelectTargetFrameworkAndDeviceIfNeeded(logger, out selector))
165159
{
160+
selector?.Dispose();
166161
// If --list-devices was specified, this is a successful exit
167162
return ListDevices ? 0 : 1;
168163
}
@@ -206,13 +201,17 @@ public int Execute()
206201

207202
// Deploy step: Call DeployToDevice target if available
208203
// This must run even with --no-build, as the user may have selected a different device
209-
if (selector is not null && !selector.TryDeployToDevice())
204+
if (selector is not null)
210205
{
211-
// Only error if we have a valid project (not a .sln file, etc.)
212-
if (selector.HasValidProject)
206+
if (!selector.TryDeployToDevice())
213207
{
214-
throw new GracefulException(CliCommandStrings.RunCommandDeployFailed);
208+
// Only error if we have a valid project (not a .sln file, etc.)
209+
if (selector.HasValidProject)
210+
{
211+
throw new GracefulException(CliCommandStrings.RunCommandDeployFailed);
212+
}
215213
}
214+
selector.Dispose();
216215
}
217216

218217
ICommand targetCommand = GetTargetCommand(projectFactory, cachedRunProperties, logger);
@@ -246,14 +245,22 @@ public int Execute()
246245

247246
/// <summary>
248247
/// Checks if target framework selection and device selection are needed.
249-
/// Uses a single RunCommandSelector instance for both operations, re-evaluating
250-
/// the project after framework selection to get the correct device list.
248+
/// Creates a RunCommandSelector for framework and device selection.
249+
/// Note: Project evaluation requires restore to have completed first.
251250
/// </summary>
252-
/// <param name="selector">The selector to use for framework and device selection</param>
251+
/// <param name="logger">Optional logger for MSBuild operations</param>
252+
/// <param name="selector">Output parameter for the created selector, needed for later deployment</param>
253253
/// <returns>True if we can continue, false if we should exit</returns>
254-
private bool TrySelectTargetFrameworkAndDeviceIfNeeded(RunCommandSelector selector)
254+
private bool TrySelectTargetFrameworkAndDeviceIfNeeded(FacadeLogger? logger, out RunCommandSelector? selector)
255255
{
256-
Debug.Assert(selector is not null);
256+
Debug.Assert(ProjectFileFullPath is not null);
257+
258+
// Create the selector - note that project evaluation happens lazily, not here
259+
selector = new RunCommandSelector(
260+
ProjectFileFullPath,
261+
MSBuildArgs,
262+
Interactive,
263+
logger);
257264

258265
var globalProperties = CommonRunHelpers.GetGlobalPropertiesFromArgs(MSBuildArgs);
259266

src/Cli/dotnet/Commands/Run/RunCommandSelector.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal sealed class RunCommandSelector : IDisposable
2626
private readonly string _projectFilePath;
2727
private readonly Dictionary<string, string> _globalProperties;
2828
private readonly FacadeLogger? _binaryLogger;
29-
private readonly ILogger? _consoleLogger;
29+
private readonly MSBuildArgs _msbuildArgs;
3030
private readonly bool _isInteractive;
3131

3232
private ProjectCollection? _collection;
@@ -53,7 +53,7 @@ public RunCommandSelector(
5353
_globalProperties = CommonRunHelpers.GetGlobalPropertiesFromArgs(msbuildArgs);
5454
_isInteractive = isInteractive;
5555
_binaryLogger = binaryLogger;
56-
_consoleLogger = CommonRunHelpers.GetConsoleLogger(msbuildArgs);
56+
_msbuildArgs = msbuildArgs;
5757
}
5858

5959
/// <summary>
@@ -120,8 +120,9 @@ private bool OpenProjectIfNeeded([NotNullWhen(true)] out ProjectInstance? projec
120120
{
121121
if (_project is not null)
122122
{
123-
Debug.Assert(_projectInstance is not null);
124-
projectInstance = _projectInstance;
123+
// Create a fresh ProjectInstance for each build operation
124+
// to avoid accumulating state from previous builds
125+
projectInstance = _project.CreateProjectInstance();
125126
return true;
126127
}
127128

@@ -478,12 +479,12 @@ public bool TryDeployToDevice()
478479

479480
/// <summary>
480481
/// Gets the list of loggers to use for MSBuild operations.
482+
/// Creates a fresh console logger each time to avoid disposal issues when calling Build() multiple times.
481483
/// </summary>
482484
private IEnumerable<ILogger> GetLoggers()
483485
{
484486
if (_binaryLogger is not null)
485487
yield return _binaryLogger;
486-
if (_consoleLogger is not null)
487-
yield return _consoleLogger;
488+
yield return CommonRunHelpers.GetConsoleLogger(_msbuildArgs);
488489
}
489490
}

0 commit comments

Comments
 (0)