| File: Dcp\ExecutableLaunchPolicy.cs | Web Access |
| Project: src\src\Aspire.Hosting\Aspire.Hosting.csproj (Aspire.Hosting) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma warning disable ASPIREPROJECTS001 #pragma warning disable ASPIREEXTENSION001 using System.Diagnostics; using Aspire.Hosting.ApplicationModel; using Microsoft.Extensions.Configuration; namespace Aspire.Hosting.Dcp; internal sealed class ExecutableLaunchPolicy(IConfiguration configuration) { private readonly IConfiguration _configuration = configuration; public ExecutableLaunchDecision Decide(IResource resource) { if (resource.HasAnnotationOfType<ForceProcessExecutionAnnotation>() || resource.HasPersistentLifetime()) { return new( ExecutableLaunchMechanism.Process, ExecutableLaunchMode.NoDebug, projectLaunchMode: GetProjectLaunchMode()); } var supportsDebugging = resource.SupportsDebugging(_configuration, out var debugSupport); if (resource is ProjectResource) { if (resource.TryGetLastAnnotation<ProjectLaunchArgsOverrideAnnotation>(out _)) { // A project launch override is a complete Process invocation. A supported custom debug producer // may still contribute optional launch metadata, matching the existing MAUI behavior, but its // success does not determine whether the Process invocation can run. var metadataProducer = supportsDebugging && debugSupport is { LaunchConfigurationType: not KnownLaunchConfigurationTypes.Project } ? debugSupport : null; return new( ExecutableLaunchMechanism.Process, GetLaunchMode(metadataProducer?.LaunchConfigurationType), metadataProducer, projectLaunchMode: GetProjectLaunchMode()); } if (supportsDebugging && debugSupport is not null) { return new( ExecutableLaunchMechanism.Ide, GetLaunchMode(debugSupport.LaunchConfigurationType), debugSupport, projectLaunchMode: GetProjectLaunchMode()); } if (ShouldUseCompatibilityProjectLaunch(resource, debugSupport)) { return new( ExecutableLaunchMechanism.Ide, GetLaunchMode(KnownLaunchConfigurationTypes.Project), useCompatibilityProjectLaunchConfiguration: true, projectLaunchMode: GetProjectLaunchMode()); } } else if (supportsDebugging && debugSupport is not null) { return new( ExecutableLaunchMechanism.Ide, GetLaunchMode(debugSupport.LaunchConfigurationType), debugSupport); } return new( ExecutableLaunchMechanism.Process, ExecutableLaunchMode.NoDebug, projectLaunchMode: GetProjectLaunchMode()); } private bool ShouldUseCompatibilityProjectLaunch( IResource resource, SupportsDebuggingAnnotation? debugSupport) { if (string.IsNullOrEmpty(_configuration[DcpExecutor.DebugSessionPortVar])) { return false; } if (resource.TryGetLastAnnotation<ExecutableAnnotation>(out _) && debugSupport?.LaunchConfigurationType is not null and not KnownLaunchConfigurationTypes.Project) { return false; } if (debugSupport is not null && !string.IsNullOrEmpty(_configuration[KnownConfigNames.DebugSessionInfo])) { return false; } // A directly added legacy ProjectResource may not declare a launch configuration type at all. Preserve its // historical Visual Studio-compatible behavior and treat it as a project launch whenever a debug session is // active. Project v2 resources declare their capability explicitly and do not use this compatibility path. return true; } private string GetLaunchMode(string? launchConfigurationType) { if (launchConfigurationType is KnownLaunchConfigurationTypes.Project) { return GetProjectLaunchMode(); } return _configuration[KnownConfigNames.DebugSessionRunMode] ?? ExecutableLaunchMode.NoDebug; } private string GetProjectLaunchMode() => _configuration[KnownConfigNames.DebugSessionRunMode] ?? (Debugger.IsAttached ? ExecutableLaunchMode.Debug : ExecutableLaunchMode.NoDebug); }