Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

Discovery.cs 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Unity Technologies.
  3. * Copyright (c) Microsoft Corporation. All rights reserved.
  4. * Licensed under the MIT License. See License.txt in the project root for license information.
  5. *--------------------------------------------------------------------------------------------*/
  6. using System;
  7. using System.IO;
  8. using System.Collections.Generic;
  9. using System.Diagnostics;
  10. using System.Text.RegularExpressions;
  11. using System.Linq;
  12. using UnityEngine;
  13. namespace Microsoft.Unity.VisualStudio.Editor
  14. {
  15. internal static class Discovery
  16. {
  17. internal const string ManagedWorkload = "Microsoft.VisualStudio.Workload.ManagedGame";
  18. internal static string _vsWherePath;
  19. public static void FindVSWhere()
  20. {
  21. _vsWherePath = FileUtility.GetPackageAssetFullPath("Editor", "VSWhere", "vswhere.exe");
  22. }
  23. public static IEnumerable<IVisualStudioInstallation> GetVisualStudioInstallations()
  24. {
  25. if (VisualStudioEditor.IsWindows)
  26. {
  27. foreach (var installation in QueryVsWhere())
  28. yield return installation;
  29. }
  30. if (VisualStudioEditor.IsOSX)
  31. {
  32. var candidates = Directory.EnumerateDirectories("/Applications", "*.app");
  33. foreach (var candidate in candidates)
  34. {
  35. if (TryDiscoverInstallation(candidate, out var installation))
  36. yield return installation;
  37. }
  38. }
  39. }
  40. private static bool IsCandidateForDiscovery(string path)
  41. {
  42. if (File.Exists(path) && VisualStudioEditor.IsWindows && Regex.IsMatch(path, "devenv.exe$", RegexOptions.IgnoreCase))
  43. return true;
  44. if (Directory.Exists(path) && VisualStudioEditor.IsOSX && Regex.IsMatch(path, "Visual\\s?Studio(?!.*Code.*).*.app$", RegexOptions.IgnoreCase))
  45. return true;
  46. return false;
  47. }
  48. public static bool TryDiscoverInstallation(string editorPath, out IVisualStudioInstallation installation)
  49. {
  50. installation = null;
  51. if (string.IsNullOrEmpty(editorPath))
  52. return false;
  53. if (!IsCandidateForDiscovery(editorPath))
  54. return false;
  55. // On windows we use the executable directly, so we can query extra information
  56. var fvi = editorPath;
  57. // On Mac we use the .app folder, so we need to access to main assembly
  58. if (VisualStudioEditor.IsOSX)
  59. {
  60. fvi = Path.Combine(editorPath, "Contents/Resources/lib/monodevelop/bin/VisualStudio.exe");
  61. if (!File.Exists(fvi))
  62. fvi = Path.Combine(editorPath, "Contents/MonoBundle/VisualStudio.exe");
  63. if (!File.Exists(fvi))
  64. fvi = Path.Combine(editorPath, "Contents/MonoBundle/VisualStudio.dll");
  65. }
  66. if (!File.Exists(fvi))
  67. return false;
  68. // VS preview are not using the isPrerelease flag so far
  69. // On Windows FileDescription contains "Preview", but not on Mac
  70. var vi = FileVersionInfo.GetVersionInfo(fvi);
  71. var version = new Version(vi.ProductVersion);
  72. var isPrerelease = vi.IsPreRelease || string.Concat(editorPath, "/" + vi.FileDescription).ToLower().Contains("preview");
  73. installation = new VisualStudioInstallation()
  74. {
  75. IsPrerelease = isPrerelease,
  76. Name = $"{vi.FileDescription}{(isPrerelease && VisualStudioEditor.IsOSX ? " Preview" : string.Empty)} [{version.ToString(3)}]",
  77. Path = editorPath,
  78. Version = version
  79. };
  80. return true;
  81. }
  82. #region VsWhere Json Schema
  83. #pragma warning disable CS0649
  84. [Serializable]
  85. internal class VsWhereResult
  86. {
  87. public VsWhereEntry[] entries;
  88. public static VsWhereResult FromJson(string json)
  89. {
  90. return JsonUtility.FromJson<VsWhereResult>("{ \"" + nameof(VsWhereResult.entries) + "\": " + json + " }");
  91. }
  92. public IEnumerable<VisualStudioInstallation> ToVisualStudioInstallations()
  93. {
  94. foreach (var entry in entries)
  95. {
  96. yield return new VisualStudioInstallation()
  97. {
  98. Name = $"{entry.displayName} [{entry.catalog.productDisplayVersion}]",
  99. Path = entry.productPath,
  100. IsPrerelease = entry.isPrerelease,
  101. Version = Version.Parse(entry.catalog.buildVersion)
  102. };
  103. }
  104. }
  105. }
  106. [Serializable]
  107. internal class VsWhereEntry
  108. {
  109. public string displayName;
  110. public bool isPrerelease;
  111. public string productPath;
  112. public VsWhereCatalog catalog;
  113. }
  114. [Serializable]
  115. internal class VsWhereCatalog
  116. {
  117. public string productDisplayVersion; // non parseable like "16.3.0 Preview 3.0"
  118. public string buildVersion;
  119. }
  120. #pragma warning restore CS3021
  121. #endregion
  122. private static IEnumerable<VisualStudioInstallation> QueryVsWhere()
  123. {
  124. var progpath = _vsWherePath;
  125. if (string.IsNullOrWhiteSpace(progpath))
  126. return Enumerable.Empty<VisualStudioInstallation>();
  127. var result = ProcessRunner.StartAndWaitForExit(progpath, "-prerelease -format json -utf8");
  128. if (!result.Success)
  129. throw new Exception($"Failure while running vswhere: {result.Error}");
  130. // Do not catch any JsonException here, this will be handled by the caller
  131. return VsWhereResult
  132. .FromJson(result.Output)
  133. .ToVisualStudioInstallations();
  134. }
  135. }
  136. }