Modified dotnet runtime system to use the user's installed dotnet runtime instead.

This commit is contained in:
Kah Wei 2023-06-30 00:13:10 +08:00
parent 0f7d86543f
commit 94fa84bf78
2 changed files with 99 additions and 2 deletions

View File

@ -21,6 +21,8 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies
#include <shlwapi.h> // PathRemoveFileSpecA
#include "Tools/Logger/SHLogger.h"
#include "Tools/Utilities/SHExecUtilities.h"
#include "Tools/Utilities/SHStringUtilities.h"
namespace SHADE
{
@ -59,6 +61,10 @@ namespace SHADE
if (initialised)
throw std::runtime_error("[DotNetRuntime] Failed to initialise as it was already initialised or was deinitialised into an invalid state.");
const auto DOT_NET_PATH = getDotNetRuntimePath();
if (!DOT_NET_PATH)
throw std::runtime_error("[DotNetRuntime] .NET Runtime installation is missing.");
// Get the current executable directory
std::string runtimePath(MAX_PATH, '\0');
GetModuleFileNameA(nullptr, runtimePath.data(), MAX_PATH);
@ -70,7 +76,7 @@ namespace SHADE
if (coreClr == nullptr)
{
// Construct the CoreCLR path
std::string coreClrPath(runtimePath); // Works
std::string coreClrPath("C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\5.0.17"); // Works
coreClrPath += "\\coreclr.dll";
// Load the CoreCLR DLL
@ -94,7 +100,7 @@ namespace SHADE
// trusted system assemblies (similar to the .NET Framework GAC).
// For this host (as with most), assemblies next to CoreCLR will
// be included in the TPA list
std::string tpaList = buildTpaList(runtimePath);
std::string tpaList = buildTpaList(DOT_NET_PATH->string());
// Define CoreCLR properties
std::array propertyKeys =
@ -195,4 +201,82 @@ namespace SHADE
throw std::runtime_error(oss.str());
}
}
std::optional<std::filesystem::path> SHDotNetRuntime::getDotNetRuntimePath()
{
// Check if dotnet is installed
const auto DOT_NET_PATH = std::filesystem::path(L"C:\\Program Files\\dotnet\\dotnet.exe");
if (!std::filesystem::exists(DOT_NET_PATH))
return {};
// Execute dotnet to search for
const auto RUNTIME_SEARCH = SHExecUtilties::ExecBlockingProcess(DOT_NET_PATH.wstring(), L" --list-runtimes", true, false);
if (RUNTIME_SEARCH.Code != 0)
return {};
// Remove all except Microsoft.NETCore.App entries
auto runtimeEntries = SHStringUtilities::Split(RUNTIME_SEARCH.StdOutput, L'\n');
std::erase_if(runtimeEntries, [](const std::wstring& str)
{
return str.find(L".NETCore.App") == std::wstring::npos;
});
// Early exit if there is none
if (runtimeEntries.empty())
return {};
// Select the highest version
std::wstring highestVersion;
int major = 0; int minor = 0; int revision = 0;
for (const auto& entry : runtimeEntries)
{
auto start = entry.find_first_of(L"1234567890");
auto end = entry.find_last_of(L"1234567890");
// No version string found
if (start == std::wstring::npos)
continue;
// Grab the version string and tokenize it to parts
const std::wstring VER_STR = entry.substr(start, end - start + 1);
const auto VERSION_TOKENS = SHStringUtilities::Split(VER_STR, L'.');
// Invalid version string
if (VERSION_TOKENS.size() < 3)
continue;
// Get version strings
const auto thisMajor = stoi(VERSION_TOKENS[0]);
const auto thisMinor = stoi(VERSION_TOKENS[1]);
const auto thisRevision = stoi(VERSION_TOKENS[2]);
if (major > thisRevision)
continue;
if (minor > thisMinor)
continue;
if (revision > thisRevision)
continue;
major = thisMajor;
minor = thisMinor;
revision = thisRevision;
highestVersion = VER_STR;
}
// No suitable version found
if (highestVersion.empty())
return {};
// Extract path string
const std::wstring& ENTRY = runtimeEntries[0];
const auto START = ENTRY.find_first_of(L'[');
const auto END = ENTRY.find_last_of(L']');
// - Can't extract string
if (START == std::wstring::npos || END == std::wstring::npos)
return {};
// - Extract string
const std::wstring DIR_PATH = ENTRY.substr(START + 1, END - START - 1);
// Form resulting path based on found version
return std::filesystem::path(DIR_PATH) / highestVersion;
}
}

View File

@ -201,6 +201,19 @@ namespace SHADE
*/
/***********************************************************************************/
static void throwIfFailed(const std::string& errMsg, int resultCode);
/***********************************************************************************/
/*!
\brief
Searches for the dotnet runtime binary folder and returns it if it exists.
If multiple versions are present, the latest version will be returned.
\return
The path to the dotnet runtime binary folder. Null if none was found.
*/
/***********************************************************************************/
static std::optional<std::filesystem::path> getDotNetRuntimePath();
};
}