Skip to content
This repository was archived by the owner on Apr 2, 2020. It is now read-only.

Commit ec096fe

Browse files
authored
Support VS2017 using vswhere (#113)
1 parent 09bc722 commit ec096fe

1 file changed

Lines changed: 89 additions & 2 deletions

File tree

Protobuild.Manager/IDEControl/VisualStudioIDEControl.cs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.IO;
5+
using System.Linq;
46
using System.Runtime.InteropServices;
57
using System.Runtime.InteropServices.ComTypes;
68
using System.Threading.Tasks;
@@ -12,12 +14,18 @@ internal class VisualStudioIDEControl : IIDEControl
1214
private readonly RuntimeServer _runtimeServer;
1315
private readonly IProcessLog _processLog;
1416
private readonly IExecution _execution;
17+
private readonly IProtobuildProvider _protobuildProvider;
1518

16-
public VisualStudioIDEControl(RuntimeServer runtimeServer, IProcessLog processLog, IExecution execution)
19+
public VisualStudioIDEControl(
20+
RuntimeServer runtimeServer,
21+
IProcessLog processLog,
22+
IExecution execution,
23+
IProtobuildProvider protobuildProvider)
1724
{
1825
_runtimeServer = runtimeServer;
1926
_processLog = processLog;
2027
_execution = execution;
28+
_protobuildProvider = protobuildProvider;
2129
}
2230

2331
public async Task LoadSolution(string modulePath, string moduleName, string targetPlatform, string oldPlatformOnFail, bool isProtobuild)
@@ -326,9 +334,88 @@ public async Task CloseGenerateAndLoadSolution(string modulePath, string moduleN
326334
private async Task<dynamic> LaunchVisualStudio(string modulePath, string moduleName, string targetPlatform, int? vspid, dynamic existing)
327335
{
328336
_runtimeServer.Set("status", "Starting Visual Studio...");
337+
338+
// Newer installs of Visual Studio (like 2017) don't create registry entries for MSBuild, so we have to
339+
// use a tool called vswhere in order to find MSBuild on these systems. This call will implicitly install
340+
// the vswhere package if it's not already installed.
341+
var protobuild = await _protobuildProvider.GetProtobuild(status =>
342+
{
343+
_runtimeServer.Set("status", status);
344+
});
345+
List<string> installations = null;
346+
if (protobuild != null && File.Exists(protobuild))
347+
{
348+
try
349+
{
350+
var processStartInfo = new ProcessStartInfo();
351+
processStartInfo.FileName = protobuild;
352+
processStartInfo.Arguments = "--execute vswhere -products * -requires Microsoft.VisualStudio.Workload.CoreEditor -property installationPath";
353+
processStartInfo.UseShellExecute = false;
354+
processStartInfo.RedirectStandardOutput = true;
355+
processStartInfo.CreateNoWindow = true;
356+
var process = Process.Start(processStartInfo);
357+
var installationsString = process.StandardOutput.ReadToEnd();
358+
installations = installationsString.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
359+
process.WaitForExit();
360+
361+
if (process.ExitCode != 0)
362+
{
363+
// Try to install vswhere (it may not be installed).
364+
processStartInfo = new ProcessStartInfo();
365+
processStartInfo.FileName = protobuild;
366+
processStartInfo.Arguments = "--install Protobuild.vswhere";
367+
processStartInfo.UseShellExecute = false;
368+
processStartInfo.RedirectStandardOutput = true;
369+
processStartInfo.CreateNoWindow = true;
370+
process = Process.Start(processStartInfo);
371+
process.WaitForExit();
372+
373+
if (process.ExitCode != 0)
374+
{
375+
// Can't use vswhere.
376+
}
377+
else
378+
{
379+
// Install worked, try again.
380+
processStartInfo = new ProcessStartInfo();
381+
processStartInfo.FileName = protobuild;
382+
processStartInfo.Arguments = "--execute vswhere -products * -requires Microsoft.VisualStudio.Workload.CoreEditor -property installationPath";
383+
processStartInfo.UseShellExecute = false;
384+
processStartInfo.RedirectStandardOutput = true;
385+
processStartInfo.CreateNoWindow = true;
386+
process = Process.Start(processStartInfo);
387+
installationsString = process.StandardOutput.ReadToEnd();
388+
installations = installationsString.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
389+
process.WaitForExit();
390+
}
391+
}
392+
}
393+
catch (Exception ex)
394+
{
395+
// Can't find any installations.
396+
}
397+
}
329398

330-
var versions = new[] {"14.0", "12.0", "11.0", "10.0"};
331399
var started = false;
400+
401+
if (installations != null)
402+
{
403+
// Check if the IDE is present in any of those installation paths.
404+
foreach (var basePath in installations)
405+
{
406+
var ideLocation = Path.Combine(basePath, "Common7\\IDE\\devenv.exe");
407+
if (File.Exists(ideLocation))
408+
{
409+
Process.Start(
410+
ideLocation,
411+
"\"" + Path.Combine(modulePath, moduleName + "." + targetPlatform + ".sln") + "\"");
412+
started = true;
413+
break;
414+
}
415+
}
416+
}
417+
418+
var versions = new[] {"14.0", "12.0", "11.0", "10.0"};
332419
foreach (var version in versions)
333420
{
334421
var idePath = @"C:\Program Files (x86)\Microsoft Visual Studio " + version +

0 commit comments

Comments
 (0)