using System.Reflection; namespace Hua.Todo.Maui.Platforms.Windows; internal static class WebView2RuntimeDetector { /// /// 判断当前 Windows 系统是否可用 WebView2 Runtime。 /// 优先通过已知的 Evergreen 安装目录探测(避免因托管程序集缺失/裁剪导致误判), /// 其次再尝试通过 WebView2 SDK 的 CoreWebView2Environment.GetAvailableBrowserVersionString 获取版本。 /// /// 检测到的运行时版本(若可用)。 /// 若系统存在可用的 WebView2 Runtime,则返回 true;否则返回 false internal static bool IsRuntimeInstalled(out string? version) { version = null; try { version = TryGetEvergreenVersionFromKnownLocations(); if (!string.IsNullOrWhiteSpace(version)) { return true; } var type = Type.GetType("Microsoft.Web.WebView2.Core.CoreWebView2Environment, Microsoft.Web.WebView2.Core"); if (type == null) { return false; } version = TryInvokeVersionGetter(type); return !string.IsNullOrWhiteSpace(version); } catch { return false; } } private static string? TryGetEvergreenVersionFromKnownLocations() { var candidates = new[] { Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Microsoft", "EdgeWebView", "Application"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Microsoft", "EdgeWebView", "Application"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "EdgeWebView", "Application"), }; Version? best = null; foreach (var baseDir in candidates) { if (string.IsNullOrWhiteSpace(baseDir) || !Directory.Exists(baseDir)) { continue; } foreach (var dir in Directory.EnumerateDirectories(baseDir)) { var name = Path.GetFileName(dir); if (!Version.TryParse(name, out var v)) { continue; } if (!File.Exists(Path.Combine(dir, "msedgewebview2.exe"))) { continue; } if (best == null || v > best) { best = v; } } } return best?.ToString(); } private static string? TryInvokeVersionGetter(Type environmentType) { var noArg = environmentType.GetMethod("GetAvailableBrowserVersionString", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, Type.EmptyTypes, null); if (noArg != null) { return noArg.Invoke(null, null) as string; } var oneArg = environmentType.GetMethod("GetAvailableBrowserVersionString", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, new[] { typeof(string) }, null); if (oneArg != null) { return oneArg.Invoke(null, new object?[] { null }) as string; } return null; } }