diff --git a/BannerlordModEditor.Common.Tests/Services/SdkCheckerServiceTests.cs b/BannerlordModEditor.Common.Tests/Services/SdkCheckerServiceTests.cs new file mode 100644 index 00000000..1679be24 --- /dev/null +++ b/BannerlordModEditor.Common.Tests/Services/SdkCheckerServiceTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Threading.Tasks; +using Xunit; +using BannerlordModEditor.Common.Services; + +namespace BannerlordModEditor.Common.Tests.Services +{ + public class SdkCheckerServiceTests + { + private readonly SdkCheckerService _service; + + public SdkCheckerServiceTests() + { + _service = new SdkCheckerService(); + } + + [Fact] + public void GetDownloadUrl_ReturnsValidUrl() + { + var url = _service.GetDownloadUrl(); + Assert.NotNull(url); + Assert.Contains("dotnet", url); + } + + [Fact] + public async Task CheckSdkAsync_ReturnsValidInfo() + { + var info = await _service.CheckSdkAsync(); + + Assert.NotNull(info); + Assert.NotNull(info.RecommendedVersion); + Assert.NotNull(info.DownloadUrl); + } + + [Fact] + public void CheckSdk_ReturnsValidInfo() + { + var info = _service.CheckSdk(); + + Assert.NotNull(info); + Assert.NotNull(info.RecommendedVersion); + Assert.NotNull(info.DownloadUrl); + } + + [Fact] + public void IsSdkInstalled_ReturnsBoolean() + { + var result = _service.IsSdkInstalled(); + Assert.IsType(result); + } + + [Fact] + public void GetSdkVersion_ReturnsStringOrNull() + { + var result = _service.GetSdkVersion(); + Assert.True(result == null || !string.IsNullOrEmpty(result)); + } + + [Fact] + public void GetInstalledVersions_ReturnsList() + { + var versions = _service.GetInstalledVersions(); + Assert.NotNull(versions); + } + } +} diff --git a/BannerlordModEditor.Common/Services/SdkCheckerService.cs b/BannerlordModEditor.Common/Services/SdkCheckerService.cs new file mode 100644 index 00000000..1997f244 --- /dev/null +++ b/BannerlordModEditor.Common/Services/SdkCheckerService.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace BannerlordModEditor.Common.Services +{ + public class SdkInfo + { + public bool IsInstalled { get; set; } + public string? Version { get; set; } + public string? Path { get; set; } + public List InstalledVersions { get; set; } = new(); + public string? RecommendedVersion { get; set; } + public string? DownloadUrl { get; set; } + } + + public interface ISdkCheckerService + { + Task CheckSdkAsync(); + SdkInfo CheckSdk(); + bool IsSdkInstalled(); + string? GetSdkVersion(); + List GetInstalledVersions(); + string GetDownloadUrl(); + } + + public class SdkCheckerService : ISdkCheckerService + { + private const string RecommendedSdkVersion = "9.0.100"; + private const string DownloadUrlBase = "https://dotnet.microsoft.com/download/dotnet/9.0"; + + public async Task CheckSdkAsync() + { + return await Task.Run(() => CheckSdk()); + } + + public SdkInfo CheckSdk() + { + var info = new SdkInfo + { + IsInstalled = IsSdkInstalled(), + Version = GetSdkVersion(), + Path = GetSdkPath(), + InstalledVersions = GetInstalledVersions(), + RecommendedVersion = RecommendedSdkVersion, + DownloadUrl = GetDownloadUrl() + }; + + return info; + } + + public bool IsSdkInstalled() + { + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "dotnet", + Arguments = "--version", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + process.Start(); + var output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + + return process.ExitCode == 0 && !string.IsNullOrWhiteSpace(output); + } + catch + { + return false; + } + } + + public string? GetSdkVersion() + { + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "dotnet", + Arguments = "--version", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + process.Start(); + var output = process.StandardOutput.ReadToEnd().Trim(); + process.WaitForExit(); + + return process.ExitCode == 0 ? output : null; + } + catch + { + return null; + } + } + + public List GetInstalledVersions() + { + var versions = new List(); + + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "dotnet", + Arguments = "--list-sdks", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + process.Start(); + var output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + + if (process.ExitCode == 0) + { + foreach (var line in output.Split('\n', StringSplitOptions.RemoveEmptyEntries)) + { + var parts = line.Trim().Split(' '); + if (parts.Length > 0) + { + versions.Add(parts[0]); + } + } + } + } + catch + { + } + + return versions; + } + + public string GetDownloadUrl() + { + return DownloadUrlBase; + } + + private string? GetSdkPath() + { + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "dotnet", + Arguments = "--list-sdks", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + process.Start(); + var output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + + if (process.ExitCode == 0) + { + foreach (var line in output.Split('\n', StringSplitOptions.RemoveEmptyEntries)) + { + var bracketIndex = line.IndexOf('['); + if (bracketIndex > 0) + { + var path = line[(bracketIndex + 1)..].TrimEnd(']'); + if (Directory.Exists(path)) + { + return path; + } + } + } + } + } + catch + { + } + + return null; + } + } +}