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