// Copyright Keysight Technologies 2012-2025 // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, you can obtain one at http://mozilla.org/MPL/2.0/. using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace OpenTap { internal static class ExecutorSubProcess { public class EnvVarNames { public static string TpmInteropPipeName = "TPM_PIPE"; public static string ParentProcessExeDir = "TPM_PARENTPROCESSDIR"; public static string OpenTapInitDirectory = "OPENTAP_INIT_DIRECTORY"; } } internal static class ExecutorClient { /// /// Is this process an isolated sub process of tap.exe /// public static bool IsRunningIsolated => Environment.GetEnvironmentVariable(ExecutorSubProcess.EnvVarNames.ParentProcessExeDir) != null; /// /// Is this process a sub process of tap.exe /// public static bool IsExecutorMode => Environment.GetEnvironmentVariable(ExecutorSubProcess.EnvVarNames.TpmInteropPipeName) != null; /// /// The directory containing the OpenTAP installation. /// This is usually the value of the environment variable OPENTAP_INIT_DIRECTORY set by tap.exe /// If this value is not set, use the location of OpenTap.dll instead /// In some cases, when running isolated this is that value but from the parent process. /// public static string ExeDir { get { if (IsRunningIsolated) return Environment.GetEnvironmentVariable(ExecutorSubProcess.EnvVarNames.ParentProcessExeDir); else { var exePath = Environment.GetEnvironmentVariable(ExecutorSubProcess.EnvVarNames.OpenTapInitDirectory); if (exePath != null) return exePath; // Referencing OpenTap.dll causes the file to become locked. // Ensure OpenTap.dll is only loaded if the environment variable is not set. // This should only happen if OpenTAP was not loaded through tap.exe. return GetOpenTapDllLocation(); } } } public static string Dotnet => _dotnet ??= mineDotnet(); private static string _dotnet = null; private static string mineDotnet() { // Ensure dotnet is always assigned. "dotnet' is used as a fallback, in which case the system // will try to resolve it from the current PATH // Look for dotnet.exe on windows var executable = Path.DirectorySeparatorChar == '\\' ? "dotnet.exe" : "dotnet"; try { // 1. Try to check which `dotnet` instance launched the current application string mainModulePath = Process.GetCurrentProcess().MainModule?.FileName; if (!string.IsNullOrWhiteSpace(mainModulePath) && Path.GetFileName(mainModulePath).Equals(executable, StringComparison.OrdinalIgnoreCase)) { return mainModulePath; } } catch { // ignore potential permission errors } try { // 2. Find dotnet based on runtime information var runtime = RuntimeEnvironment.GetRuntimeDirectory(); if (!string.IsNullOrWhiteSpace(runtime) && Directory.Exists(runtime)) { var dir = new DirectoryInfo(runtime); while (dir != null) { var candidate = System.IO.Path.Combine(dir.FullName, executable); if (File.Exists(candidate)) { return candidate; } dir = dir.Parent; } } } catch { // ignore } return "dotnet"; } [MethodImpl(MethodImplOptions.NoInlining)] static string GetOpenTapDllLocation() => Path.GetDirectoryName(typeof(PluginSearcher).Assembly.Location); } }