Skip to content

Commit 8b52612

Browse files
committed
Use vswhere to locate Visual Studio installations
1 parent 3c0ce95 commit 8b52612

File tree

2 files changed

+21
-82
lines changed

2 files changed

+21
-82
lines changed

build/Build.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626

2727
<ItemGroup>
2828
<PackageReference Include="Cake.FileHelpers" Version="7.0.0" />
29-
<PackageReference Include="Cake.Frosting" Version="5.0.0" />
30-
<PackageReference Include="Microsoft.VisualStudio.Setup.Configuration.Interop" Version="3.*" PrivateAssets="all" />
29+
<PackageReference Include="Cake.Frosting" Version="5.0.0" />
3130
</ItemGroup>
3231

3332
<ItemGroup>

build/BuildWindowsTask.cs

Lines changed: 20 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11

2-
using Microsoft.VisualStudio.Setup.Configuration;
3-
using System.Runtime.InteropServices;
4-
52
namespace BuildScripts;
63

74
[TaskName("Build Windows")]
@@ -52,7 +49,7 @@ private bool IsOnPATH(string process)
5249
if (!process.EndsWith(".exe"))
5350
process += ".exe";
5451

55-
// check if process exist on PATH env
52+
// Check if process exist on PATH env
5653

5754
var split = Environment.GetEnvironmentVariable("PATH")?.Split(';');
5855
if (split != null)
@@ -70,86 +67,29 @@ private bool IsOnPATH(string process)
7067

7168
private string GetVisualStudioPath()
7269
{
73-
// This code to retrieve where Visual Studio is installed is adapted from
74-
// https://github.com/microsoft/MSBuildLocator
75-
// Surprisingly, this package has code to retrieve a VS installation but
76-
// this feature is disabled from the public nuget... so adapting it from source
77-
78-
// This will only detect Visual Studio 2015 and above
79-
80-
string path = string.Empty;
81-
Version version = new Version();
82-
83-
try
70+
// We can use vswhere.exe which ships with VS2017 and later.
71+
// Microsoft guarantees that it is always installed in %ProgramFiles(x86)%\Microsoft Visual Studio\Installer
72+
73+
System.Diagnostics.Process process = new System.Diagnostics.Process();
74+
process.StartInfo.FileName = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%"), "Microsoft Visual Studio\\Installer\\vswhere.exe");
75+
process.StartInfo.Arguments = "-latest";
76+
process.StartInfo.UseShellExecute = false;
77+
process.StartInfo.RedirectStandardOutput = true;
78+
process.StartInfo.CreateNoWindow = true;
79+
process.Start();
80+
81+
string result = process.StandardOutput.ReadToEnd();
82+
83+
if (!string.IsNullOrEmpty(result))
8484
{
85-
// This code is not obvious. See the sample (link above) for reference.
86-
var query = (ISetupConfiguration2)GetQuery();
87-
var e = query.EnumAllInstances();
88-
89-
int fetched;
90-
var instances = new ISetupInstance[1];
91-
do
85+
var lines = result.Split("\r\n");
86+
foreach (var line in lines)
9287
{
93-
// Call e.Next to query for the next instance (single item or nothing returned).
94-
e.Next(1, instances, out fetched);
95-
if (fetched <= 0) continue;
96-
97-
var instance = (ISetupInstance2)instances[0];
98-
InstanceState state = instance.GetState();
99-
100-
// If the install was complete
101-
if (state == InstanceState.Complete ||
102-
(state.HasFlag(InstanceState.Registered) && state.HasFlag(InstanceState.NoRebootRequired)))
103-
{
104-
if (!Version.TryParse(instance.GetInstallationVersion(), out var current))
105-
continue;
106-
107-
// We want the highest version installed
108-
if (current <= version)
109-
continue;
110-
111-
version = current;
112-
path = instance.GetInstallationPath();
113-
}
88+
if (line.StartsWith("installationPath: "))
89+
return line.Substring(18);
11490
}
115-
while (fetched > 0);
116-
}
117-
catch (COMException)
118-
{
119-
}
120-
catch (DllNotFoundException)
121-
{
122-
// This is OK, VS "15" or greater likely not installed.
12391
}
12492

125-
return path;
93+
return string.Empty;
12694
}
127-
128-
private static ISetupConfiguration GetQuery()
129-
{
130-
const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154);
131-
132-
try
133-
{
134-
// Try to CoCreate the class object.
135-
return new SetupConfiguration();
136-
}
137-
138-
catch (COMException ex) when (ex.ErrorCode == REGDB_E_CLASSNOTREG)
139-
{
140-
// Try to get the class object using app-local call.
141-
ISetupConfiguration query;
142-
var result = GetSetupConfiguration(out query, IntPtr.Zero);
143-
144-
if (result < 0)
145-
throw new COMException($"Failed to get {nameof(query)}", result);
146-
147-
return query;
148-
}
149-
}
150-
151-
[DllImport("Microsoft.VisualStudio.Setup.Configuration.Native.dll", ExactSpelling = true, PreserveSig = true)]
152-
private static extern int GetSetupConfiguration(
153-
[MarshalAs(UnmanagedType.Interface)][Out] out ISetupConfiguration configuration,
154-
IntPtr reserved);
15595
}

0 commit comments

Comments
 (0)