Skip to content

Commit b95523a

Browse files
love-lingerFreyLuis
andcommitted
feature: detect Visual Studio Preview as external tools (#1553)
Co-authored-by: Luis Frey <[email protected]> Signed-off-by: leo <[email protected]>
1 parent 8f9094f commit b95523a

File tree

3 files changed

+44
-14
lines changed

3 files changed

+44
-14
lines changed

src/App.JsonCodeGen.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Text.Json;
34
using System.Text.Json.Serialization;
45

@@ -64,6 +65,7 @@ public override void Write(Utf8JsonWriter writer, DataGridLength value, JsonSeri
6465
[JsonSerializable(typeof(Models.ThemeOverrides))]
6566
[JsonSerializable(typeof(Models.Version))]
6667
[JsonSerializable(typeof(Models.RepositorySettings))]
68+
[JsonSerializable(typeof(List<Models.VisualStudioInstance>))]
6769
[JsonSerializable(typeof(ViewModels.Preferences))]
6870
internal partial class JsonCodeGen : JsonSerializerContext { }
6971
}

src/Models/ExternalTool.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ public void Open(string repo)
4848
private Func<string, string> _execArgsGenerator = null;
4949
}
5050

51+
public class VisualStudioInstance
52+
{
53+
[JsonPropertyName("displayName")]
54+
public string DisplayName { get; set; } = string.Empty;
55+
56+
[JsonPropertyName("productPath")]
57+
public string ProductPath { get; set; } = string.Empty;
58+
}
59+
5160
public class JetBrainsState
5261
{
5362
[JsonPropertyName("version")]

src/Native/Windows.cs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Runtime.InteropServices;
66
using System.Runtime.Versioning;
77
using System.Text;
8+
using System.Text.Json;
89

910
using Avalonia;
1011
using Avalonia.Controls;
@@ -189,7 +190,7 @@ public string FindTerminal(Models.ShellOrTerminal shell)
189190
finder.Fleet(() => Path.Combine(localAppDataDir, @"Programs\Fleet\Fleet.exe"));
190191
finder.FindJetBrainsFromToolbox(() => Path.Combine(localAppDataDir, @"JetBrains\Toolbox"));
191192
finder.SublimeText(FindSublimeText);
192-
finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio);
193+
FindVisualStudio(finder);
193194
return finder.Tools;
194195
}
195196

@@ -371,23 +372,41 @@ private string FindSublimeText()
371372
return string.Empty;
372373
}
373374

374-
private string FindVisualStudio()
375+
private void FindVisualStudio(Models.ExternalToolsFinder finder)
375376
{
376-
var localMachine = Microsoft.Win32.RegistryKey.OpenBaseKey(
377-
Microsoft.Win32.RegistryHive.LocalMachine,
378-
Microsoft.Win32.RegistryView.Registry64);
377+
var vswhere = Environment.ExpandEnvironmentVariables(@"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe");
378+
if (!File.Exists(vswhere))
379+
return;
379380

380-
// Get default class for VisualStudio.Launcher.sln - the handler for *.sln files
381-
if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is { } launcher)
381+
var startInfo = new ProcessStartInfo();
382+
startInfo.FileName = vswhere;
383+
startInfo.Arguments = "-format json -prerelease -utf8";
384+
startInfo.UseShellExecute = false;
385+
startInfo.CreateNoWindow = true;
386+
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
387+
startInfo.RedirectStandardOutput = true;
388+
startInfo.StandardOutputEncoding = Encoding.UTF8;
389+
390+
try
382391
{
383-
// Get actual path to the executable
384-
if (launcher.GetValue(string.Empty) is string CLSID &&
385-
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is { } devenv &&
386-
devenv.GetValue(string.Empty) is string localServer32)
387-
return localServer32!.Trim('\"');
388-
}
392+
using var proc = Process.Start(startInfo);
393+
var output = proc.StandardOutput.ReadToEnd();
394+
proc.WaitForExit();
389395

390-
return string.Empty;
396+
if (proc.ExitCode == 0)
397+
{
398+
var instances = JsonSerializer.Deserialize(output, JsonCodeGen.Default.ListVisualStudioInstance);
399+
foreach (var instance in instances)
400+
{
401+
var exec = instance.ProductPath;
402+
finder.TryAdd(instance.DisplayName, "vs", () => exec, GenerateCommandlineArgsForVisualStudio);
403+
}
404+
}
405+
}
406+
catch
407+
{
408+
// Just ignore.
409+
}
391410
}
392411

393412
private string FindCursor()

0 commit comments

Comments
 (0)