#include "pch.h" #include "DotnetInstallation.h" #include #include #include namespace fs = std::filesystem; namespace updating { constexpr size_t REQUIRED_MINIMAL_PATCH = 20; bool dotnet_is_installed() { auto runtimes = exec_and_read_output(LR"(dotnet --list-runtimes)"); if (!runtimes) { return false; } std::regex dotnet3_1_x{ R"(Microsoft\.WindowsDesktop\.App\s3\.1\.(\d+))" }; size_t latestPatchInstalled = 0; using rexit = std::sregex_iterator; for (auto it = rexit{ begin(*runtimes), end(*runtimes), dotnet3_1_x }; it != rexit{}; ++it) { if (!it->ready() || it->size() < 2) { continue; } auto patchNumberGroup = (*it)[1]; if (!patchNumberGroup.matched) { continue; } const auto patchString = patchNumberGroup.str(); size_t patch = 0; if (auto [_, ec] = std::from_chars(&*begin(patchString), &*end(patchString), patch); ec == std::errc()) { latestPatchInstalled = std::max(patch, latestPatchInstalled); } } return latestPatchInstalled >= REQUIRED_MINIMAL_PATCH; } std::optional download_dotnet() { const wchar_t DOTNET_DESKTOP_DOWNLOAD_LINK[] = L"https://download.visualstudio.microsoft.com/download/pr/93c69a29-d379-4a5d-bb9e-3116cc14de41/907bbc52446d8bb7baa0c6faebde1d44/windowsdesktop-runtime-3.1.20-win-x64.exe"; const wchar_t DOTNET_DESKTOP_FILENAME[] = L"windowsdesktop-runtime.exe"; auto dotnet_download_path = fs::temp_directory_path() / DOTNET_DESKTOP_FILENAME; winrt::Windows::Foundation::Uri download_link{ DOTNET_DESKTOP_DOWNLOAD_LINK }; const size_t max_attempts = 3; bool download_success = false; for (size_t i = 0; i < max_attempts; ++i) { try { http::HttpClient client; client.download(download_link, dotnet_download_path).wait(); download_success = true; break; } catch (...) { // couldn't download } } return download_success ? std::make_optional(dotnet_download_path) : std::nullopt; } bool install_dotnet(fs::path dotnet_download_path, const bool silent = false) { SHELLEXECUTEINFOW sei{ sizeof(sei) }; sei.fMask = { SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE }; sei.lpFile = dotnet_download_path.c_str(); sei.nShow = SW_SHOWNORMAL; std::wstring dotnet_flags = L"/install "; dotnet_flags += silent ? L"/quiet" : L"/passive"; sei.lpParameters = dotnet_flags.c_str(); if (ShellExecuteExW(&sei) != TRUE) { return false; } WaitForSingleObject(sei.hProcess, INFINITE); CloseHandle(sei.hProcess); return true; } }