use dotnet .dll and read launch settings

This commit is contained in:
Matt Parker
2025-08-24 13:16:02 +10:00
parent b394f7e655
commit 356a535085
4 changed files with 94 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
using Ardalis.GuardClauses;
using Microsoft.Build.Evaluation;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
namespace SharpIDE.Application.Features.Evaluation;
@@ -13,7 +14,15 @@ public static class ProjectEvaluation
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
var project = _projectCollection.LoadProject(projectFilePath);
Console.WriteLine($"ProjectEvaluation: loaded {project.FullPath}");
//Console.WriteLine($"ProjectEvaluation: loaded {project.FullPath}");
return project;
}
public static string? GetOutputDllFullPath(SharpIdeProjectModel projectModel)
{
var project = _projectCollection.GetLoadedProjects(projectModel.FilePath).Single();
var targetPath = project.GetPropertyValue("TargetPath");
Guard.Against.NullOrWhiteSpace(targetPath, nameof(targetPath));
return targetPath;
}
}

View File

@@ -0,0 +1,68 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
namespace SharpIDE.Application.Features.Run;
public static class LaunchSettingsParser
{
private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
{
PropertyNameCaseInsensitive = true,
ReadCommentHandling = JsonCommentHandling.Skip
};
public static async Task<List<ProjectLaunchSettingsModel>> GetLaunchSettingsProfiles(SharpIdeProjectModel projectModel)
{
var launchSettingsFilePath = Path.Combine(Path.GetDirectoryName(projectModel.FilePath)!, "Properties", "launchSettings.json");
var launchSettingsFile = new FileInfo(launchSettingsFilePath);
if (launchSettingsFile.Exists is false)
{
return [];
}
await using var stream = launchSettingsFile.OpenRead();
var launchSettings = await JsonSerializer.DeserializeAsync<LaunchSettings>(stream, _jsonSerializerOptions);
if (launchSettings is null) return [];
var result = launchSettings.Profiles.Select(s => new ProjectLaunchSettingsModel
{
LaunchProfileName = s.Key,
CommandLineArgs = s.Value.CommandName,
DotNetRunMessages = s.Value.DotnetRunMessages,
LaunchBrowser = s.Value.LaunchBrowser,
LaunchUrl = s.Value.LaunchUrl,
ApplicationUrl = s.Value.ApplicationUrl,
EnvironmentVariables = s.Value.EnvironmentVariables
}).ToList();
return result;
}
}
public class ProjectLaunchSettingsModel
{
public required string? LaunchProfileName { get; set; }
public required string? CommandLineArgs { get; set; }
public required bool LaunchBrowser { get; set; }
public required string? LaunchUrl { get; set; }
public required string? ApplicationUrl { get; set; }
public required bool DotNetRunMessages { get; set; }
public required Dictionary<string, string> EnvironmentVariables { get; init; }
}
// Json models
public class LaunchSettings
{
public required Dictionary<string, Profile> Profiles { get; set; }
}
public class Profile
{
public string CommandName { get; set; }
public bool DotnetRunMessages { get; set; }
public bool LaunchBrowser { get; set; }
public string LaunchUrl { get; set; }
public string ApplicationUrl { get; set; }
public Dictionary<string, string> EnvironmentVariables { get; set; }
}

View File

@@ -2,6 +2,7 @@
using System.Threading.Channels;
using Ardalis.GuardClauses;
using AsyncReadProcess;
using SharpIDE.Application.Features.Evaluation;
using SharpIDE.Application.Features.Events;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
@@ -22,16 +23,29 @@ public class RunService
if (project.RunningCancellationTokenSource is not null) throw new InvalidOperationException($"Project {project.Name} is already running with a cancellation token source.");
project.RunningCancellationTokenSource = new CancellationTokenSource();
var dllFullPath = ProjectEvaluation.GetOutputDllFullPath(project);
var launchProfiles = await LaunchSettingsParser.GetLaunchSettingsProfiles(project);
var launchProfile = launchProfiles.FirstOrDefault();
try
{
var processStartInfo = new ProcessStartInfo2
{
FileName = "dotnet",
Arguments = $"run --project \"{project.FilePath}\" --no-restore",
WorkingDirectory = Path.GetDirectoryName(project.FilePath),
//Arguments = $"run --project \"{project.FilePath}\" --no-restore",
Arguments = $"\"{dllFullPath}\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
EnvironmentVariables = []
};
if (launchProfile is not null)
{
foreach (var envVar in launchProfile.EnvironmentVariables)
{
processStartInfo.EnvironmentVariables[envVar.Key] = envVar.Value;
}
if (launchProfile.ApplicationUrl != null) processStartInfo.EnvironmentVariables["ASPNETCORE_URLS"] = launchProfile.ApplicationUrl;
}
var process = new Process2
{

View File

@@ -16,7 +16,7 @@
<!-- If any Microsoft.Build.*.dll (Excluding Locator) ends up in the output, it will be prioritised for loading by MSBuild Nodes -->
<PackageReference Include="OmniSharp.Extensions.DebugAdapter.Client" Version="0.19.9" />
<PackageReference Include="Ardalis.GuardClauses" Version="5.0.0" />
<PackageReference Include="AsyncReadProcess" Version="1.0.0-preview11" />
<PackageReference Include="AsyncReadProcess" Version="1.0.0-preview14" />
<PackageReference Include="Microsoft.Build" Version="17.14.8" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Framework" Version="17.14.8" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.9.1" />