diff --git a/src/Runner.Client/Program.cs b/src/Runner.Client/Program.cs index 9dddbc5f044..00fcc66357b 100644 --- a/src/Runner.Client/Program.cs +++ b/src/Runner.Client/Program.cs @@ -264,7 +264,7 @@ private static async Task CreateRunner(string binpath, Parameters parameter Console.WriteLine(e.Data); }; #if !OS_LINUX && !OS_WINDOWS && !OS_OSX && !X64 && !X86 && !ARM && !ARM64 - var dotnet = WhichUtil.Which("dotnet", true); + var dotnet = Sdk.Utils.DotNetMuxer.MuxerPath ?? WhichUtil.Which("dotnet", true); string ext = ".dll"; #else string ext = IOUtil.ExeExtension; @@ -497,7 +497,7 @@ private static async Task CreateExternalRunner(string binpath, Parameters p // Use embedded runner to configure external github agent, otherwise only port 80 or 443 are possible to use for configuration #if !OS_LINUX && !OS_WINDOWS && !OS_OSX && !X64 && !X86 && !ARM && !ARM64 arguments = $"\"{Path.Join(binpath, "Runner.Listener.dll")}\" {arguments}"; - file = WhichUtil.Which("dotnet", true); + file = Sdk.Utils.DotNetMuxer.MuxerPath ?? WhichUtil.Which("dotnet", true); #else file = Path.Join(binpath, $"Runner.Listener{ext}"); #endif @@ -535,7 +535,7 @@ private static async Task CreateExternalRunner(string binpath, Parameters p if(!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { #if !OS_LINUX && !OS_WINDOWS && !OS_OSX && !X64 && !X86 && !ARM && !ARM64 arguments = $"\"{Path.Join(binpath, "Runner.Client.dll")}\" spawn \"{file}\" {arguments}"; - file = WhichUtil.Which("dotnet", true); + file = Sdk.Utils.DotNetMuxer.MuxerPath ?? WhichUtil.Which("dotnet", true); #else arguments = $"spawn \"{file}\" {arguments}"; file = Path.Join(binpath, $"Runner.Client{ext}"); @@ -1293,7 +1293,7 @@ static int Main(string[] args) invoker.ErrorDataReceived += _out; } #if !OS_LINUX && !OS_WINDOWS && !OS_OSX && !X64 && !X86 && !ARM && !ARM64 - var dotnet = WhichUtil.Which("dotnet", true); + var dotnet = Sdk.Utils.DotNetMuxer.MuxerPath ?? WhichUtil.Which("dotnet", true); string ext = ".dll"; #else string ext = IOUtil.ExeExtension; diff --git a/src/Runner.Language.Server/Runner.Language.Server.csproj b/src/Runner.Language.Server/Runner.Language.Server.csproj index e9be5a20488..5e75ca2f6e2 100644 --- a/src/Runner.Language.Server/Runner.Language.Server.csproj +++ b/src/Runner.Language.Server/Runner.Language.Server.csproj @@ -17,6 +17,8 @@ Exe + + false diff --git a/src/Runner.Listener/JobDispatcher.cs b/src/Runner.Listener/JobDispatcher.cs index f6f0cddefe0..751c48ebcdd 100644 --- a/src/Runner.Listener/JobDispatcher.cs +++ b/src/Runner.Listener/JobDispatcher.cs @@ -473,7 +473,7 @@ private async Task RunAsync(Pipelines.AgentJobRequestMessage message, string orc string workerFileName = Path.Combine(assemblyDirectory, $"{_workerProcessName}{ext}"); string arguments = "spawnclient " + pipeHandleOut + " " + pipeHandleIn; #if !OS_LINUX && !OS_WINDOWS && !OS_OSX && !X64 && !X86 && !ARM && !ARM64 - var dotnet = WhichUtil.Which("dotnet", true); + var dotnet = global::Sdk.Utils.DotNetMuxer.MuxerPath ?? WhichUtil.Which("dotnet", true); arguments = $"\"{workerFileName}\" {arguments}"; workerFileName = dotnet; #endif diff --git a/src/Runner.Sdk/Util/IOUtil.cs b/src/Runner.Sdk/Util/IOUtil.cs index 4721dd2f58b..05ea74b6ce6 100644 --- a/src/Runner.Sdk/Util/IOUtil.cs +++ b/src/Runner.Sdk/Util/IOUtil.cs @@ -558,5 +558,13 @@ private static void RemoveReadOnly(FileSystemInfo item) item.Attributes = item.Attributes & ~FileAttributes.ReadOnly; } } + + public static string GetDotnet() { + var procPath = Environment.ProcessPath; + if(Path.GetFileNameWithoutExtension(procPath) == "dotnet" && Path.GetExtension(procPath) == ExeExtension) { + return procPath; + } + return WhichUtil.Which("dotnet", true); + } } } diff --git a/src/Runner.Worker/RunnerPluginManager.cs b/src/Runner.Worker/RunnerPluginManager.cs index 35a3d829b7b..64427d96cc4 100644 --- a/src/Runner.Worker/RunnerPluginManager.cs +++ b/src/Runner.Worker/RunnerPluginManager.cs @@ -102,7 +102,7 @@ public async Task RunPluginActionAsync(IExecutionContext context, string plugin, string arguments = $"action \"{plugin}\""; #if !OS_LINUX && !OS_WINDOWS && !OS_OSX && !X64 && !X86 && !ARM && !ARM64 - var dotnet = WhichUtil.Which("dotnet", true); + var dotnet = global::Sdk.Utils.DotNetMuxer.MuxerPath ?? WhichUtil.Which("dotnet", true); arguments = $"\"{file}\" {arguments}"; file = dotnet; #endif diff --git a/src/Sdk/Utils/DotNetMuxer.cs b/src/Sdk/Utils/DotNetMuxer.cs new file mode 100644 index 00000000000..d1592c46f74 --- /dev/null +++ b/src/Sdk/Utils/DotNetMuxer.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// System.AppContext.GetData is not available in these frameworks + +/// https://github.com/dotnet/aspnetcore/blob/main/src/Shared/CommandLineUtils/Utilities/DotNetMuxer.cs + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Sdk.Utils +{ +/// +/// Utilities for finding the "dotnet.exe" file from the currently running .NET Core application +/// +public static class DotNetMuxer +{ + private const string MuxerName = "dotnet"; + + static DotNetMuxer() + { + MuxerPath = TryFindMuxerPath(); + } + + /// + /// The full filepath to the .NET Core muxer. + /// + public static string? MuxerPath { get; } + + /// + /// Finds the full filepath to the .NET Core muxer, + /// or returns a string containing the default name of the .NET Core muxer ('dotnet'). + /// + /// The path or a string named 'dotnet'. + public static string MuxerPathOrDefault() + => MuxerPath ?? MuxerName; + + private static string? TryFindMuxerPath() + { + var expectedFileName = MuxerName; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + expectedFileName += ".exe"; + } + + // If the currently running process is dotnet(.exe), return that path + var mainModuleFullPath = Process.GetCurrentProcess().MainModule?.FileName; + var mainModuleFileName = Path.GetFileName(mainModuleFullPath); + if (string.Equals(expectedFileName, mainModuleFileName, StringComparison.OrdinalIgnoreCase)) + { + return mainModuleFullPath; + } + + // The currently running process may not be dotnet(.exe). For example, + // it might be "testhost(.exe)" when running tests. + // In this case, we can get the location where the CLR is installed, + // and find dotnet(.exe) relative to that path. + var runtimeDirectory = RuntimeEnvironment.GetRuntimeDirectory(); + var candidateDotNetExePath = Path.Combine(runtimeDirectory, "..", "..", "..", expectedFileName); + if (File.Exists(candidateDotNetExePath)) + { + var normalizedPath = Path.GetFullPath(candidateDotNetExePath); + return normalizedPath; + } + + return null; + } +} +} diff --git a/src/runner-server-vscode/package.json b/src/runner-server-vscode/package.json index 3b0158bd15e..e76e3973cce 100644 --- a/src/runner-server-vscode/package.json +++ b/src/runner-server-vscode/package.json @@ -43,7 +43,7 @@ ] }, "scripts": { - "build": "dotnet publish ../Runner.Language.Server --no-self-contained -p:BUILD_OS=Any -p:RuntimeFrameworkVersion=6.0.0 --output native" + "build": "dotnet publish ../Runner.Language.Server --no-self-contained -p:UseAppHost=false -p:BUILD_OS=Any -p:RuntimeFrameworkVersion=6.0.0 --output native" }, "devDependencies": { "@types/vscode": "^1.73.0", diff --git a/src/runner-server-web-vscode/package.json b/src/runner-server-web-vscode/package.json index af48a07a7ad..73258ee56d7 100644 --- a/src/runner-server-web-vscode/package.json +++ b/src/runner-server-web-vscode/package.json @@ -17,6 +17,17 @@ "activationEvents": [ "onLanguage:yaml" ], + "contributes": { + "semanticTokenScopes": [ + { + "scopes": { + "constant.defaultLibrary": ["constant.language"], + "constant.numeric": ["constant.numeric"], + "punctuation": ["meta.embedded"] + } + } + ] + }, "browser": "./client/dist/browserClientMain", "scripts": { "vscode:prepublish": "npm run build",