public bool TryGetDotnetPathByArchitecture()

in src/Microsoft.TestPlatform.CoreUtilities/Helpers/DotnetHostHelper.cs [121:279]


    public bool TryGetDotnetPathByArchitecture(PlatformArchitecture targetArchitecture, out string muxerPath)
    {
        if (_processHelper.GetCurrentProcessArchitecture() == targetArchitecture)
        {
            string currentProcessFileName = _processHelper.GetCurrentProcessFileName();
            if (Path.GetFileName(currentProcessFileName) != _muxerName)
            {
                EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Target architecture is the same as the current process architecture '{targetArchitecture}', but the current process is not a muxer: '{currentProcessFileName}'");
            }
            else
            {
                muxerPath = currentProcessFileName;
                EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Target architecture is the same as the current process architecture '{targetArchitecture}', and the current process is a muxer, using that: '{muxerPath}'");
                return true;
            }
        }

        // We used similar approach as the runtime resolver.
        // https://github.com/dotnet/runtime/blob/main/src/native/corehost/fxr_resolver.cpp#L55

        bool isWinOs = _environment.OperatingSystem == PlatformOperatingSystem.Windows;
        EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Searching for muxer named '{_muxerName}'");

        // Try to search using env vars in the order
        // DOTNET_ROOT_{arch}
        // DOTNET_ROOT(x86) if X86 on Win (here we cannot check if current process is WOW64 because this is SDK process arch and not real host arch so it's irrelevant)
        //                  "DOTNET_ROOT(x86) is used instead when running a 32-bit executable on a 64-bit OS."
        // DOTNET_ROOT
        string envKey = $"DOTNET_ROOT_{targetArchitecture.ToString().ToUpperInvariant()}";

        // Try on arch specific env var
        string envVar = _environmentVariableHelper.GetEnvironmentVariable(envKey);

        // Try on non virtualized x86 var(should happen only on non-x86 architecture)
        if ((envVar == null || !_fileHelper.DirectoryExists(envVar)) &&
            targetArchitecture == PlatformArchitecture.X86 && _environment.OperatingSystem == PlatformOperatingSystem.Windows)
        {
            envKey = $"DOTNET_ROOT(x86)";
            envVar = _environmentVariableHelper.GetEnvironmentVariable(envKey);
        }

        // Try on default DOTNET_ROOT
        if (envVar == null || !_fileHelper.DirectoryExists(envVar))
        {
            envKey = "DOTNET_ROOT";
            envVar = _environmentVariableHelper.GetEnvironmentVariable(envKey);
        }

        if (envVar != null)
        {
            // If directory specified by env vars does not exists, it's like env var doesn't exists as well.
            if (!_fileHelper.DirectoryExists(envVar))
            {
                EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Folder specified by env variable does not exist: '{envVar}={envKey}'");
            }
            else
            {
                muxerPath = Path.Combine(envVar, _muxerName);
                if (!_fileHelper.Exists(muxerPath))
                {
                    // If environment variable was specified, and the directory it points at exists, but it does not contain a muxer, or the muxer is incompatible with the target architecture
                    // we stop the search to be compliant with the approach that apphost (compiled .NET executables) use to find the muxer.
                    EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Folder specified by env variable does not contain any muxer: '{envVar}={envKey}'");
                    muxerPath = null;
                    return false;
                }

                if (!IsValidArchitectureMuxer(targetArchitecture, muxerPath))
                {
                    EqtTrace.Verbose($"DotnetHostHelper: Invalid muxer resolved using env var key '{envKey}' in '{envVar}'");
                    muxerPath = null;
                    return false;
                }

                EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer compatible with '{targetArchitecture}' resolved from env variable '{envKey}' in '{muxerPath}'");
                return true;
            }
        }

        EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer was not found using DOTNET_ROOT* env variables.");

        // Try to search for global registration
        muxerPath = isWinOs ? GetMuxerFromGlobalRegistrationWin(targetArchitecture) : GetMuxerFromGlobalRegistrationOnUnix(targetArchitecture);

        if (muxerPath != null)
        {
            if (!_fileHelper.Exists(muxerPath))
            {
                // If muxer doesn't exists or it's wrong we stop the search
                EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer file not found for global registration '{muxerPath}'");
                muxerPath = null;
                return false;
            }

            if (!IsValidArchitectureMuxer(targetArchitecture, muxerPath))
            {
                // If muxer is wrong we stop the search
                EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer resolved using global registration is not compatible with the target architecture: '{muxerPath}'");
                muxerPath = null;
                return false;
            }

            EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer compatible with '{targetArchitecture}' resolved from global registration: '{muxerPath}'");
            return true;
        }

        EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer not found using global registrations");

        // Try searching in default installation location if it exists
        if (isWinOs)
        {
            // If we're on x64/arm64 SDK and target is x86 we need to search on non virtualized windows folder
            if ((_environment.Architecture == PlatformArchitecture.X64 || _environment.Architecture == PlatformArchitecture.ARM64) &&
                 targetArchitecture == PlatformArchitecture.X86)
            {
                muxerPath = Path.Combine(_environmentVariableHelper.GetEnvironmentVariable("ProgramFiles(x86)"), "dotnet", _muxerName);
            }
            else
            {
                // If we're on ARM and target is x64 we expect correct installation inside x64 folder
                muxerPath = _environment.Architecture == PlatformArchitecture.ARM64 && targetArchitecture == PlatformArchitecture.X64
                    ? Path.Combine(_environmentVariableHelper.GetEnvironmentVariable("ProgramFiles"), "dotnet", "x64", _muxerName)
                    : Path.Combine(_environmentVariableHelper.GetEnvironmentVariable("ProgramFiles"), "dotnet", _muxerName);
            }
        }
        else
        {
            if (_environment.OperatingSystem == PlatformOperatingSystem.OSX)
            {
                // If we're on ARM and target is x64 we expect correct installation inside x64 folder
                muxerPath = _environment.Architecture == PlatformArchitecture.ARM64 && targetArchitecture == PlatformArchitecture.X64
                    ? Path.Combine("/usr/local/share/dotnet/x64", _muxerName)
                    : Path.Combine("/usr/local/share/dotnet", _muxerName);
            }
            else
            {
                muxerPath = Path.Combine("/usr/share/dotnet", _muxerName);
            }
        }

        if (!_fileHelper.Exists(muxerPath))
        {
            // If muxer doesn't exists we stop the search
            EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer was not found in default installation location: '{muxerPath}'");
            muxerPath = null;
            return false;
        }

        if (!IsValidArchitectureMuxer(targetArchitecture, muxerPath))
        {
            // If muxer is wrong we stop the search
            EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer resolved in default installation path is not compatible with the target architecture: '{muxerPath}'");
            muxerPath = null;
            return false;
        }

        EqtTrace.Verbose($"DotnetHostHelper.TryGetDotnetPathByArchitecture: Muxer compatible with '{targetArchitecture}' resolved from default installation path: '{muxerPath}'");
        return true;
    }