private static List <IDEInfo> BuildIDEInfos() { var ideInfos = new List <IDEInfo>(); // Visual Studio 15.0 (2017) and later try { var configuration = new SetupConfiguration(); var instances = configuration.EnumAllInstances(); instances.Reset(); var inst = new ISetupInstance[1]; while (true) { instances.Next(1, inst, out int pceltFetched); if (pceltFetched <= 0) { break; } try { var inst2 = inst[0] as ISetupInstance2; if (inst2 == null) { continue; } // Only deal with VS2019+ if (!Version.TryParse(inst2.GetInstallationVersion(), out var version) || version.Major < 15) { continue; } var installationPath = inst2.GetInstallationPath(); var buildToolsPath = Path.Combine(installationPath, "MSBuild", "Current", "Bin"); if (!Directory.Exists(buildToolsPath)) { buildToolsPath = null; } var idePath = Path.Combine(installationPath, "Common7", "IDE"); var devenvPath = Path.Combine(idePath, "devenv.exe"); if (!File.Exists(devenvPath)) { devenvPath = null; } var vsixInstallerPath = Path.Combine(idePath, "VSIXInstaller.exe"); if (!File.Exists(vsixInstallerPath)) { vsixInstallerPath = null; } var displayName = inst2.GetDisplayName(); // Try to append nickname (if any) try { var nickname = inst2.GetProperties().GetValue("nickname") as string; if (!string.IsNullOrEmpty(nickname)) { displayName = $"{displayName} ({nickname})"; } else { var installationName = inst2.GetInstallationName(); // In case of Preview, we have: // "installationName": "VisualStudioPreview/16.4.0-pre.6.0+29519.161" // "channelId": "VisualStudio.16.Preview" if (installationName.Contains("Preview")) { displayName = displayName + " (Preview)"; } } } catch (COMException) { } try { var minimumRequiredState = InstanceState.Local | InstanceState.Registered; if ((inst2.GetState() & minimumRequiredState) != minimumRequiredState) { continue; } } catch (COMException) { continue; } var ideInfo = new IDEInfo(version, displayName, installationPath, inst2.IsComplete()) { BuildToolsPath = buildToolsPath, DevenvPath = devenvPath, VsixInstallerVersion = VSIXInstallerVersion.VS2019AndFutureVersions, VsixInstallerPath = vsixInstallerPath, }; // Fill packages foreach (var package in inst2.GetPackages()) { ideInfo.PackageVersions[package.GetId()] = package.GetVersion(); } ideInfos.Add(ideInfo); } catch (Exception) { // Something might have happened inside Visual Studio Setup code (had FileNotFoundException in GetInstallationPath() for example) // Let's ignore this instance } } } catch (COMException comException) when(comException.HResult == REGDB_E_CLASSNOTREG) { // COM is not registered. Assuming no instances are installed. } return(ideInfos); }
private static List <IDEInfo> BuildIDEInfos() { var ideInfos = new List <IDEInfo>(); // Visual Studio 16.0 (2019) and later try { var setupInstancesEnum = new SetupConfiguration().EnumAllInstances(); setupInstancesEnum.Reset(); var inst = new ISetupInstance[1]; while (true) { setupInstancesEnum.Next(1, inst, out int numFetched); if (numFetched <= 0) { break; } try { var setupInstance2 = inst[0] as ISetupInstance2; if (setupInstance2 == null) { continue; } // Only examine VS2019+ if (!Version.TryParse(setupInstance2.GetInstallationVersion(), out var installationVersion) || installationVersion.Major < 16) { continue; } var displayName = setupInstance2.GetDisplayName(); // Try to append nickname (if any) try { var nickname = setupInstance2.GetProperties().GetValue("nickname") as string; if (!string.IsNullOrEmpty(nickname)) { displayName = $"{displayName} ({nickname})"; } else { var installationName = setupInstance2.GetInstallationName(); // In case of Preview, we have: // "installationName": "VisualStudioPreview/16.4.0-pre.6.0+29519.161" // "channelId": "VisualStudio.16.Preview" if (installationName.Contains("Preview")) { displayName += " (Preview)"; } } } catch (COMException) { } try { var minimumRequiredState = InstanceState.Local | InstanceState.Registered; if ((setupInstance2.GetState() & minimumRequiredState) != minimumRequiredState) { continue; } } catch (COMException) { continue; } var ideInfo = new IDEInfo(installationVersion, displayName, setupInstance2.GetInstallationPath(), setupInstance2.GetInstanceId(), setupInstance2.IsComplete()); // Fill packages foreach (var package in setupInstance2.GetPackages()) { ideInfo.PackageVersions[package.GetId()] = package.GetVersion(); } ideInfos.Add(ideInfo); } catch (Exception) { // Something might have happened inside Visual Studio Setup code (had FileNotFoundException in GetInstallationPath() for example) // Let's ignore this instance } } } catch (COMException comException) when(comException.HResult == REGDB_E_CLASSNOTREG) { // COM is not registered. Assuming no instances are installed. } return(ideInfos); }