public static string[] GetInstancePaths() { var instancePaths = new List <string>(); var query = new SetupConfiguration(); var e = query.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { instancePaths.Add(instances[0].GetInstallationPath()); } } while (fetched > 0); return(instancePaths.ToArray()); }
/// <summary> /// Gets the installed version /// </summary> /// <param name="configurationSuffix"></param> /// <returns>The Visual Studio metadata</returns> public static VisualStudio GetInstalledVisualStudio(string configurationSuffix) { var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { return(GetInstance(instances[0], configurationSuffix)); } }while (fetched > 0); return(default(VisualStudio)); }
private bool TryGetVCToolsPath(out string batchPath) { var configuration = new SetupConfiguration(); var enumInstances = configuration.EnumInstances(); int fetched; var instances = new ISetupInstance[1]; do { enumInstances.Next(1, instances, out fetched); if (fetched <= 0) { continue; } if (!(instances[0] is ISetupInstance2 instance)) { continue; } var packages = instance.GetPackages(); foreach (var package in packages) { if (package.GetId() != "Microsoft.VisualStudio.Component.VC.Tools.x86.x64") { continue; } var rootPath = instance.ResolvePath(); batchPath = Directory.GetFiles(rootPath, "VsDevCmd.bat", SearchOption.AllDirectories) .FirstOrDefault(); return(true); } } while (fetched > 0); batchPath = null; return(false); }
public Vs2017SetupConfig() { try { _setupConfig = new SetupConfiguration(); } catch (Exception ex) { throw new Exception($"Cannot create a new SetupConfiguration for Visual Studio", ex); } var setupConfig2 = (ISetupConfiguration2)_setupConfig; var e = setupConfig2.EnumAllInstances(); var helper = (ISetupHelper)_setupConfig; int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { var instance2 = (ISetupInstance2)instances[0]; var instanceInfo = new VSInstanceInfo { Id = instance2.GetInstanceId(), Name = instance2.GetInstallationName(), Version = instance2.GetInstallationVersion(), DispName = instance2.GetDisplayName(), Description = instance2.GetDescription(), ResPath = instance2.ResolvePath(), EnginePath = instance2.GetEnginePath(), InstalledPath = instance2.GetInstallationPath(), ProductPath = instance2.GetProductPath() }; _instanceInfos.Add(instanceInfo); } }while (fetched > 0); }
private static string GetPathOfFirstInstalledVisualStudioInstance() { Tuple <Version, string> highestVersion = null; try { IEnumSetupInstances setupInstances = new SetupConfiguration().EnumAllInstances(); ISetupInstance[] instances = new ISetupInstance[1]; for (setupInstances.Next(1, instances, out int fetched); fetched > 0; setupInstances.Next(1, instances, out fetched)) { ISetupInstance2 instance = (ISetupInstance2)instances.First(); if (instance.GetState() == InstanceState.Complete) { string installationPath = instance.GetInstallationPath(); if (!string.IsNullOrWhiteSpace(installationPath) && Version.TryParse(instance.GetInstallationVersion(), out Version version)) { if (highestVersion == null || version > highestVersion.Item1) { highestVersion = new Tuple <Version, string>(version, installationPath); } } } } if (highestVersion != null) { return(Path.Combine(highestVersion.Item2, "MSBuild", GetMSBuildVersionDirectory($"{highestVersion.Item1.Major}.0"), "Bin")); } } catch { // Ignored } return(null); }
/// <summary> /// Tries to get all vs 2017 instances. /// </summary> /// <param name="versions">Collection holding available visual studio instances</param> /// <returns>Success of the operation</returns> private static bool GetVs2017Instances(ICollection <ToolchainVersion> versions) { const int REGDB_E_CLASSNOTREG = unchecked ((int)0x80040154); try { var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { var instance = (ISetupInstance2)instances[0]; var packages = instance.GetPackages(); var toolchain = new ToolchainVersion { Directory = instance.GetInstallationPath() + @"\Common7\IDE", Version = Single.Parse(instance.GetInstallationVersion().Remove(2)), Value = null // Not used currently }; versions.Add(toolchain); } }while (fetched > 0); } catch (COMException ex) when(ex.HResult == REGDB_E_CLASSNOTREG) { Console.WriteLine("The query API is not registered. Assuming no instances are installed."); return(false); } catch (Exception ex) { Console.Error.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); return(false); } return(true); }
private static List <ISetupInstance> GetVisualStudioInstances() { List <ISetupInstance> vsInstances = new(); try { SetupConfiguration setupConfiguration = new(); ISetupConfiguration2 setupConfiguration2 = setupConfiguration; IEnumSetupInstances setupInstances = setupConfiguration2.EnumInstances(); ISetupInstance[] instances = new ISetupInstance[1]; int fetched = 0; do { setupInstances.Next(1, instances, out fetched); if (fetched > 0) { ISetupInstance2 instance = (ISetupInstance2)instances[0]; // .NET Workloads only shipped in 17.0 and later and we should only look at IDE based SKUs // such as community, professional, and enterprise. if (Version.TryParse(instance.GetInstallationVersion(), out Version version) && version.Major >= 17 && s_visualStudioProducts.Contains(instance.GetProduct().GetId())) { vsInstances.Add(instances[0]); } } }while (fetched > 0); } catch (COMException e) when(e.ErrorCode == REGDB_E_CLASSNOTREG) { // Query API not registered, good indication there are no VS installations of 15.0 or later. // Other exceptions are passed through since that likely points to a real error. } return(vsInstances); }
private static IEnumerable <IVisualStudioInfo> DetectNewVisualStudios() { SetupConfiguration configuration; try { configuration = new SetupConfiguration(); } catch (COMException ex) { // class not registered, no VS2017+ installations if ((uint)ex.HResult == 0x80040154) { yield break; } throw; } IEnumSetupInstances e = configuration.EnumAllInstances(); int fetched; ISetupInstance[] instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched <= 0) { continue; } ISetupInstance2 instance2 = (ISetupInstance2)instances[0]; string filename = Path.Combine(instance2.GetInstallationPath(), @"Common7\IDE\devenv.exe"); if (File.Exists(filename)) { yield return(new VisualStudio2017Info(Version.Parse(instance2.GetInstallationVersion()), instance2.GetDisplayName(), filename)); } }while (fetched > 0); }
/// <summary> /// Returns the path to the specified version of msbuild.exe or /// null if it could not be found /// </summary> /// <param name="msBuildMajorVersion">MSBuild major version number e.g. 15.0</param> private static string GetMSBuildPath(string msBuildMajorVersion, TestContext testContext) { // Note: we're using a Microsoft component that locates instances of VS, and then // we're searching for an expected path under VS. // A more robust and flexible approach would be to use https://www.nuget.org/packages/vswhere/ // which would allow us to search for a specific version of MSBuild directly. testContext.WriteLine($"Test setup: attempting to locate an MSBuild instance. Version: {msBuildMajorVersion}"); ISetupConfiguration config = new SetupConfiguration(); var instances = new ISetupInstance[100]; var enumerator = config.EnumInstances(); enumerator.Next(100, instances, out int fetched); if (fetched == 0) { throw new InvalidOperationException("Test setup error: no instances of Visual Studio could be located on this machine"); } string partialExePath = Path.Combine("MSBuild", msBuildMajorVersion, "Bin", "msbuild.exe"); for (int i = 0; i < fetched; i++) { var instance = instances[i]; testContext.WriteLine($"\t\tVS instance: {instance.GetDisplayName()}, {instance.GetInstallationVersion()}, {instance.GetInstallationPath()}"); var candidateExePath = instance.ResolvePath(partialExePath); if (File.Exists(candidateExePath)) { testContext.WriteLine($"\tMSBuild exe located: {candidateExePath}"); return(candidateExePath); } } testContext.WriteLine($"Test setup: MSBuild exe could not be located"); return(null); }
internal void GetVisualStudio() { SetupInstance tmp = new SetupInstance(); tmp.DisplayName = "系统默认"; tmp.InstallationPath = this.configurationViewMode.DefaultTesthostPath; tmp.TestAdapterPath = this.configurationViewMode.DefaultTestAdaptersPath; vs.Add(tmp); try { var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); var helper = (ISetupHelper)query; int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { tmp = new SetupInstance(); tmp.DisplayName = instances[0].GetDisplayName(); tmp.InstallationPath = instances[0].GetInstallationPath() + "\\Common7\\IDE\\Extensions\\TestPlatform\\"; tmp.TestAdapterPath = tmp.InstallationPath + "Extensions\\"; vs.Add(tmp); } }while (fetched > 0); } catch (COMException ex) when(ex.HResult == REGDB_E_CLASSNOTREG) { } catch (Exception) { } }
private void InvokeVsixInstaller(string tempDir, string rootSuffix) { var process = System.Diagnostics.Process.GetCurrentProcess(); var dir = Path.GetDirectoryName(process.MainModule.FileName); var exe = Path.Combine(dir, "VSIXInstaller.exe"); var configuration = new SetupConfiguration() as ISetupConfiguration; ISetupInstance instance = configuration.GetInstanceForCurrentProcess(); IEnumerable <string> vsixFiles = Directory.EnumerateFiles(tempDir, "*.vsix").Select(f => Path.GetFileName(f)); var start = new ProcessStartInfo { FileName = exe, Arguments = $"{string.Join(" ", vsixFiles)} /instanceIds:{instance.GetInstanceId()}", WorkingDirectory = tempDir, UseShellExecute = false, }; if (!string.IsNullOrEmpty(rootSuffix)) { start.Arguments += $" /rootSuffix:{rootSuffix}"; } System.Diagnostics.Process.Start(start); }
public List <VisualStudioInstanceData> GetVisualStudioInstallations() { var visualStudioInstances = new List <VisualStudioInstanceData>(); var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { var visualStudioInstance = ParseVisualStudioInstanceData(instances[0]); visualStudioInstances.Add(visualStudioInstance); } }while (fetched > 0); return(visualStudioInstances); }
private IEnumerable <(string name, string filePath, Version version)> Enumerate() { var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); var helper = (ISetupHelper)query; int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { if (TryGetInstance(instances[0], helper, out var instance)) { yield return(instance); } } }while (fetched > 0); }
private string GetVSInstallPath() { var vsPathOverride = Environment.GetEnvironmentVariable("SHARPGEN_VS_OVERRIDE"); if (!string.IsNullOrEmpty(vsPathOverride)) { return(vsPathOverride); } try { var query = new SetupConfiguration(); var enumInstances = query.EnumInstances(); int fetched; var instances = new ISetupInstance[1]; do { enumInstances.Next(1, instances, out fetched); if (fetched <= 0) { continue; } var instance2 = (ISetupInstance2)instances[0]; var state = instance2.GetState(); if ((state & InstanceState.Registered) != InstanceState.Registered) { continue; } if (instance2.GetPackages().Any(Predicate)) { return(instance2.GetInstallationPath()); } } while (fetched > 0);
static IEnumerable <ISetupInstance2> EnumerateInstances() { var query = (ISetupConfiguration2) new SetupConfiguration(); var e = query.EnumAllInstances(); var helper = (ISetupHelper)query; var instances = new List <ISetupInstance2>(); var result = new ISetupInstance[1]; int fetched; do { e.Next(1, result, out fetched); if (fetched > 0) { var instance = (ISetupInstance2)result[0]; var state = instance.GetState(); if (state == InstanceState.Complete && (state & InstanceState.Local) == InstanceState.Local) { yield return(instance); } } } while (fetched > 0); }
/// <summary> /// Returns all system includes of the installed VS 2017 instance. /// </summary> /// <param name="vsDir">Path to the visual studio installation (for identifying the correct instance)</param> /// <returns>The system includes</returns> private static List <string> GetSystemIncludesVS2017(string vsDir) { List <string> includes = new List <string>(); //They includes are in a different folder const int REGDB_E_CLASSNOTREG = unchecked ((int)0x80040154); try { var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; var regexWinSDK10Version = new Regex(@"Windows10SDK\.(\d+)\.?"); do { e.Next(1, instances, out fetched); if (fetched > 0) { var instance = (ISetupInstance2)instances[0]; if (instance.GetInstallationPath() != vsDir) { continue; } var packages = instance.GetPackages(); var vc_tools = from package in packages where package.GetId().Contains("Microsoft.VisualStudio.Component.VC.Tools") orderby package.GetId() select package; if (vc_tools.Any()) { // Tools found, get path var path = instance.GetInstallationPath(); var versionFilePath = path + @"\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"; var version = System.IO.File.ReadLines(versionFilePath).ElementAt(0).Trim(); includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\include"); includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\atlmfc\include"); } var sdks = from package in packages where package.GetId().Contains("Windows10SDK") || package.GetId().Contains("Windows81SDK") || package.GetId().Contains("Win10SDK_10") select package; var win10sdks = from sdk in sdks where sdk.GetId().Contains("Windows10SDK") select sdk; var win8sdks = from sdk in sdks where sdk.GetId().Contains("Windows81SDK") select sdk; if (win10sdks.Any()) { var sdk = win10sdks.Last(); var matchVersion = regexWinSDK10Version.Match(sdk.GetId()); string path; if (matchVersion.Success) { Environment.SpecialFolder specialFolder = Environment.Is64BitOperatingSystem ? Environment.SpecialFolder.ProgramFilesX86 : Environment.SpecialFolder.ProgramFiles; var programFiles = Environment.GetFolderPath(specialFolder); path = Path.Combine(programFiles, "Windows Kits", "10", "include", $"10.0.{matchVersion.Groups[1].Value}.0"); } else { path = "<invalid>"; } var shared = Path.Combine(path, "shared"); var um = Path.Combine(path, "um"); var winrt = Path.Combine(path, "winrt"); var ucrt = Path.Combine(path, "ucrt"); Console.WriteLine(path); if (Directory.Exists(shared) && Directory.Exists(um) && Directory.Exists(winrt) && Directory.Exists(ucrt)) { includes.Add(shared); includes.Add(um); includes.Add(winrt); includes.Add(ucrt); } } else if (win8sdks.Any()) { includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\shared"); includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\um"); includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\winrt"); } return(includes); //We've collected all information. } }while (fetched > 0); } // a COM exception means the VS 2017 COM API (therefore VS itself) is not installed, ignore catch (COMException ex) when(ex.HResult == REGDB_E_CLASSNOTREG) { } catch (Exception ex) { Console.Error.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); } return(includes); }
private static List <IDEInfo> BuildIDEInfos() { var ideInfos = new List <IDEInfo>(); // Visual Studio 14.0 (2015) var localMachine32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); using (var subkey = localMachine32.OpenSubKey($@"SOFTWARE\Microsoft\{"VisualStudio"}\{"14.0"}")) { var path = (string)subkey?.GetValue("InstallDir"); var vs14InstallPath = (path != null) ? Path.Combine(path, "devenv.exe") : null; if (vs14InstallPath != null && File.Exists(vs14InstallPath)) { var vsixInstallerPath = Path.Combine(path, "VSIXInstaller.exe"); if (!File.Exists(vsixInstallerPath)) { vsixInstallerPath = null; } ideInfos.Add(new IDEInfo("14.0", "Visual Studio 2015", path) { DevenvPath = vs14InstallPath, VsixInstallerVersion = VSIXInstallerVersion.VS2015, VsixInstallerPath = vsixInstallerPath }); } } // 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; } var installationPath = inst2.GetInstallationPath(); var buildToolsPath = Path.Combine(installationPath, "MSBuild", "15.0", "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})"; } } catch (COMException) { } try { var minimumRequiredState = InstanceState.Local | InstanceState.Registered; if ((inst2.GetState() & minimumRequiredState) != minimumRequiredState) { continue; } } catch (COMException) { continue; } var ideInfo = new IDEInfo(inst2.GetInstallationVersion(), displayName, installationPath, inst2.IsComplete()) { BuildToolsPath = buildToolsPath, DevenvPath = devenvPath, VsixInstallerVersion = VSIXInstallerVersion.VS2017AndFutureVersions, 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); }
/// <summary> /// Uses the VS SetupConfiguration COM API to resolve a path to a version-specific executable like DevEnv.exe or MSBuild.exe. /// </summary> /// <param name="buildVersionPath">Used to build a version-specific path to try to resolve.</param> /// <param name="minMajorVersion">The minimum major version to look for. This defaults to <see cref="VS2017MajorVersion"/>.</param> /// <param name="maxMajorVersion">The maximum major version to look for. This defaults to <see cref="int.MaxValue"/>.</param> /// <param name="resolvedPathMustExist">Whether the resolved version-specific path must exist. This defaults to false.</param> /// <returns>The resolved path for the highest matched version or null if no version was matched.</returns> public static string?ResolvePath( Func <Version, string> buildVersionPath, int minMajorVersion = VS2017MajorVersion, int maxMajorVersion = int.MaxValue, bool resolvedPathMustExist = false) { string? result = null; Version?resultVersion = null; // VS 2017 and up allow multiple side-by-side editions to be installed, and we have to use a COM API to enumerate the installed instances. // https://github.com/mluparu/vs-setup-samples - COM API samples // https://code.msdn.microsoft.com/Visual-Studio-Setup-0cedd331 - More Q&A about the COM API samples // https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/#comment-273625 // https://github.com/Microsoft/vswhere - A redistributable .exe for enumerating the VS instances from the command line. // https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/ const int REGDB_E_CLASSNOTREG = -2147221164; // 0x80040154 try { // From MS example: https://github.com/Microsoft/vs-setup-samples/blob/master/Setup.Configuration.CS/Program.cs SetupConfiguration configuration = new(); IEnumSetupInstances instanceEnumerator = configuration.EnumAllInstances(); int fetched; ISetupInstance[] instances = new ISetupInstance[1]; do { instanceEnumerator.Next(1, instances, out fetched); if (fetched > 0) { ISetupInstance instance = instances[0]; if (instance != null && Version.TryParse(instance.GetInstallationVersion(), out Version? version) && version.Major >= minMajorVersion && version.Major <= maxMajorVersion) { InstanceState state = ((ISetupInstance2)instance).GetState(); if (state == InstanceState.Complete) { string?versionPath = buildVersionPath?.Invoke(version); if (!string.IsNullOrEmpty(versionPath)) { string resolvedPath = instance.ResolvePath(versionPath); if ((resultVersion == null || resultVersion < version) && (!resolvedPathMustExist || File.Exists(resolvedPath) || Directory.Exists(resolvedPath))) { result = resolvedPath; resultVersion = version; // If we're looking for a single version, then we don't need to keep looking. if (minMajorVersion == maxMajorVersion) { break; } } } } } } }while (fetched > 0); } #pragma warning disable CC0004 // Catch block cannot be empty catch (COMException ex) when(ex.HResult == REGDB_E_CLASSNOTREG) { // The SetupConfiguration API is not registered, so assume no instances are installed. } catch (Exception) { // Heath Stewart (MSFT), the author of the SetupConfiguration API, says to treat any exception as "no instances installed." // https://code.msdn.microsoft.com/windowsdesktop/Visual-Studio-Setup-0cedd331/view/Discussions#content } #pragma warning restore CC0004 // Catch block cannot be empty return(result); }
public override ImmutableArray <MSBuildInstance> GetInstances() { if (PlatformHelper.IsMono) { return(NoInstances); } try { var configuration = Interop.GetSetupConfiguration(); if (configuration == null) { return(NoInstances); } var builder = ImmutableArray.CreateBuilder <MSBuildInstance>(); var instanceEnum = configuration.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { instanceEnum.Next(1, instances, out fetched); if (fetched <= 0) { continue; } var instance = (ISetupInstance2)instances[0]; var state = instance.GetState(); if (!Version.TryParse(instance.GetInstallationVersion(), out var version)) { continue; } if (state == InstanceState.Complete && instance.GetPackages().Any(package => package.GetId() == "Microsoft.VisualStudio.Component.Roslyn.Compiler")) { // Note: The code below will likely fail if MSBuild's version increments. var toolsPath = Path.Combine(instance.GetInstallationPath(), "MSBuild", "15.0", "Bin"); if (Directory.Exists(toolsPath)) { builder.Add( new MSBuildInstance( instance.GetDisplayName(), toolsPath, version, DiscoveryType.VisualStudioSetup)); } } }while (fetched < 0); return(builder.ToImmutable()); } catch (COMException ex) { return(LogExceptionAndReturnEmpty(ex)); } catch (DllNotFoundException ex) { // This is OK, since it probably means that VS 2017 or later isn't installed. // We'll log the exception for debugging though. return(LogExceptionAndReturnEmpty(ex)); } }
/// <summary> /// Returns all system includes of the installed VS 2017 instance. /// </summary> /// <param name="vsDir">Path to the visual studio installation (for identifying the correct instance)</param> /// <returns>The system includes</returns> private static List <string> GetSystemIncludesVS2017(string vsDir) { List <string> includes = new List <string>(); //They includes are in a different folder const int REGDB_E_CLASSNOTREG = unchecked ((int)0x80040154); try { var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); var helper = (ISetupHelper)query; int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { var instance = (ISetupInstance2)instances[0]; if (instance.GetInstallationPath() != vsDir) { continue; } var packages = instance.GetPackages(); var vc_tools = from package in packages where package.GetId().Contains("Microsoft.VisualStudio.Component.VC.Tools") orderby package.GetId() select package; if (vc_tools.Count() > 0) { // Tools found, get path var path = instance.GetInstallationPath(); var versionFilePath = path + @"\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"; var version = System.IO.File.ReadLines(versionFilePath).ElementAt(0).Trim(); includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\include"); includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\atlmfc\include"); } var sdks = from package in packages where package.GetId().Contains("Windows10SDK") || package.GetId().Contains("Windows81SDK") || package.GetId().Contains("Win10SDK_10") select package; var win10sdks = from sdk in sdks where sdk.GetId().Contains("Windows10SDK") select sdk; var win8sdks = from sdk in sdks where sdk.GetId().Contains("Windows81SDK") select sdk; if (win10sdks.Count() > 0) { var sdk = win10sdks.Last(); var path = @"C:\Program Files (x86)\Windows Kits\10\include\" + "10.0." + sdk.GetId().Substring(46) + ".0"; //Microsoft.VisualStudio.Component.Windows10SDK. = 46 chars var shared = Path.Combine(path, "shared"); var um = Path.Combine(path, "um"); var winrt = Path.Combine(path, "winrt"); var ucrt = Path.Combine(path, "ucrt"); Console.WriteLine(path); if (Directory.Exists(shared) && Directory.Exists(um) && Directory.Exists(winrt) && Directory.Exists(ucrt)) { includes.Add(shared); includes.Add(um); includes.Add(winrt); includes.Add(ucrt); } } else if (win8sdks.Count() > 0) { includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\shared"); includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\um"); includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\winrt"); } return(includes); //We've collected all information. } }while (fetched > 0); } catch (COMException ex) when(ex.HResult == REGDB_E_CLASSNOTREG) { Console.WriteLine("The query API is not registered. Assuming no instances are installed."); } catch (Exception ex) { Console.Error.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); } return(includes); }
/// <summary> /// Query the Visual Studio setup API to get instances of Visual Studio installed /// on the machine. Will not include anything before Visual Studio "15". /// </summary> /// <returns>Enumerable list of Visual Studio instances</returns> internal static IList <VisualStudioInstance> GetInstances() { var validInstances = new List <VisualStudioInstance>(); try { // This code is not obvious. See the sample (link above) for reference. var query = (ISetupConfiguration2)GetQuery(); var e = query.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { // Call e.Next to query for the next instance (single item or nothing returned). e.Next(1, instances, out fetched); if (fetched <= 0) { continue; } var instance = (ISetupInstance2)instances[0]; InstanceState state = instance.GetState(); if (!Version.TryParse(instance.GetInstallationVersion(), out Version version)) { continue; } // If the install was complete and a valid version, consider it. if (state == InstanceState.Complete || (state.HasFlag(InstanceState.Registered) && state.HasFlag(InstanceState.NoRebootRequired))) { bool instanceHasMSBuild = false; foreach (ISetupPackageReference package in instance.GetPackages()) { if (string.Equals(package.GetId(), "Microsoft.Component.MSBuild", StringComparison.OrdinalIgnoreCase)) { instanceHasMSBuild = true; break; } } if (instanceHasMSBuild) { validInstances.Add(new VisualStudioInstance( instance.GetDisplayName(), instance.GetInstallationPath(), version, DiscoveryType.VisualStudioSetup)); } } } while (fetched > 0); } catch (COMException) { } catch (DllNotFoundException) { // This is OK, VS "15" or greater likely not installed. } return(validInstances); }
private static ISetupInstance2?GetLatestPath() { var result = default(ISetupInstance2); var resultVersion = new Version(0, 0); try { // This code is not obvious. See the sample (link above) for reference. var query = (ISetupConfiguration2)GetQuery(); var e = query.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { // Call e.Next to query for the next instance (single item or nothing returned). e.Next(1, instances, out fetched); if (fetched <= 0) { continue; } var instance = (ISetupInstance2)instances[0]; var state = instance.GetState(); if (!Version.TryParse(instance.GetInstallationVersion(), out var version)) { continue; } // If the install was complete and a valid version, consider it. if (state == InstanceState.Complete || (state.HasFlag(InstanceState.Registered) && state.HasFlag(InstanceState.NoRebootRequired))) { var instanceHasMSBuild = false; foreach (var package in instance.GetPackages()) { if (string.Equals(package.GetId(), "Microsoft.Component.MSBuild", StringComparison.OrdinalIgnoreCase)) { instanceHasMSBuild = true; break; } } if (instanceHasMSBuild && instance is not null && version > resultVersion) { result = instance; resultVersion = version; } } }while (fetched > 0); } catch (COMException) { } catch (DllNotFoundException) { // This is OK, VS "15" or greater likely not installed. } return(result); }
//===================================================================== /// <summary> /// This is used to determine all installed Visual Studio instances /// </summary> /// <returns>A list of installed Visual Studio instances</returns> private static List <VisualStudioInstance> DetermineInstalledInstances() { var instances = new List <VisualStudioInstance>(); try { // VS 2015 and earlier install to a single location pointed to by an environment variable string vsPath = Environment.ExpandEnvironmentVariables(@"%VS140COMNTOOLS%\..\IDE"); if (!String.IsNullOrWhiteSpace(vsPath) && vsPath.IndexOf('%') == -1 && File.Exists(Path.Combine(vsPath, "devenv.exe"))) { vsPath = vsPath.Replace(@"\\..", @"\.."); instances.Add(new VisualStudioInstance { Version = "14.0", DisplayName = "Visual Studio 2015", InstallationPath = vsPath, DevEnvPath = Path.Combine(vsPath, "devenv.exe"), VSIXInstallerPath = Path.Combine(vsPath, "VSIXInstaller.exe"), AllUsersExtensionsPath = Path.Combine(vsPath, "Extensions"), XmlSchemaCachePath = Path.Combine(vsPath, @"..\..\Xml\Schemas"), UserTemplatesBaseFolder = "Visual Studio 2015" }); } // VS 2017 and later install side-by-side and no longer user environment variables to point to // their location. Instead, we query the list of installed versions and editions. var query2 = (ISetupConfiguration2) new SetupConfiguration(); var e = query2.EnumAllInstances(); var setupInstances = new ISetupInstance[1]; int fetched; do { e.Next(1, setupInstances, out fetched); if (fetched > 0) { var instance2 = (ISetupInstance2)setupInstances[0]; var state = instance2.GetState(); if (state == InstanceState.Complete && (state & InstanceState.Local) == InstanceState.Local) { vsPath = instance2.GetInstallationPath(); string userTemplatesFolder = null; if (instance2 is ISetupInstanceCatalog instanceCatalog) { var catalogProps = instanceCatalog.GetCatalogInfo(); if (catalogProps != null) { var propNames = catalogProps.GetNames(); if (propNames.Contains("productName") && propNames.Contains("productLineVersion")) { string productName = (string)catalogProps.GetValue("productName"), productLineVersion = (string)catalogProps.GetValue("productLineVersion"); userTemplatesFolder = $"{productName} {productLineVersion}"; } } } instances.Add(new VisualStudioInstance { Version = instance2.GetInstallationVersion(), DisplayName = instance2.GetDisplayName(), InstallationPath = vsPath, DevEnvPath = Path.Combine(vsPath, @"Common7\IDE\devenv.exe"), VSIXInstallerPath = Path.Combine(vsPath, @"Common7\IDE\VSIXInstaller.exe"), AllUsersExtensionsPath = Path.Combine(vsPath, @"Common7\IDE\Extensions"), XmlSchemaCachePath = Path.Combine(vsPath, @"Xml\Schemas"), UserTemplatesBaseFolder = userTemplatesFolder }); } } } while(fetched > 0); } catch (COMException ex) when(ex.HResult == REGDB_E_CLASSNOTREG) { // Ignore exceptions. We'll just assume there are no higher versions installed. System.Diagnostics.Debug.WriteLine("The query API is not registered. Assuming no instances are installed."); } catch (Exception ex) { // Ignore exceptions. We just won't list them. System.Diagnostics.Debug.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); } return(instances.OrderBy(i => i.Version).ThenBy(i => i.DisplayName).ToList()); }
public static string GetVSPathInfo() { string info = ""; // This is a slightly modified version of Heath Stewart's code. // source: (Heath Stewart, May 2016) https://github.com/microsoft/vs-setup-samples/blob/80426ad4ba10b7901c69ac0fc914317eb65deabf/Setup.Configuration.CS/Program.cs try { var query = new SetupConfiguration(); var query2 = (ISetupConfiguration2)query; var e = query2.EnumAllInstances(); var helper = (ISetupHelper)query; int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { var instance2 = (ISetupInstance2)instances[0]; var state = instance2.GetState(); info += $"InstanceId: {instance2.GetInstanceId()} ({(state == InstanceState.Complete ? "Complete" : "Incomplete")})\r\n"; var installationVersion = instances[0].GetInstallationVersion(); var version = helper.ParseVersion(installationVersion); info += $"InstallationVersion: {installationVersion} ({version})\r\n"; if ((state & InstanceState.Local) == InstanceState.Local) { info += $"InstallationPath: {instance2.GetInstallationPath()}\r\n"; } var catalog = instances[0] as ISetupInstanceCatalog; if (catalog != null) { info += $"IsPrerelease: {catalog.IsPrerelease()}\r\n"; } if ((state & InstanceState.Registered) == InstanceState.Registered) { info += $"Product: {instance2.GetProduct().GetId()}\r\n" + "Workloads:"; var workloads = from package in instance2.GetPackages() where string.Equals(package.GetType(), "Workload", StringComparison.OrdinalIgnoreCase) orderby package.GetId() select package; foreach (var workload in workloads) { info += $" {workload.GetId()}\r\n"; } } var catalogProps1 = instance2.GetProperties(); if (catalogProps1 != null) { info += "Custom properties:\r\n"; var catalogNames1 = from name in catalogProps1.GetNames() orderby name select new { Name = name, Value = catalogProps1.GetValue(name) }; foreach (var prop in catalogNames1) { info += $" {prop.Name}: {prop.Value}\r\n"; } } var catalogProps2 = catalog?.GetCatalogInfo(); if (catalogProps2 != null) { Console.WriteLine("Catalog properties:"); var catalogNames2 = from name in catalogProps2.GetNames() orderby name select new { Name = name, Value = catalogProps2.GetValue(name) }; foreach (var prop in catalogNames2) { info += $" {prop.Name}: {prop.Value}\r\n"; } } } }while (fetched > 0); } catch (COMException ex) when(Marshal.GetHRForException(ex) == unchecked ((int)0x80040154)) // check if REGDB_E_CLASSNOTREG { info = "The query API is not registered. Assuming no instances are installed.\r\n";; } catch (Exception ex) { info = $"Error 0x{Marshal.GetHRForException(ex):x8}: {ex.Message}\r\n"; } return(info); }
private static bool IsPreRelease(ISetupInstance setupInstance) { ISetupInstanceCatalog setupInstanceCatalog = (ISetupInstanceCatalog)setupInstance; return(setupInstanceCatalog.IsPrerelease()); }
/// <summary> /// This constructor services v15.1+ toolsets /// </summary> internal MsBuildToolset(ISetupInstance sxsToolset) { Path = GetMsBuildDirFromVsDir(sxsToolset.GetInstallationPath()); Version = GetMsBuildVersionFromMsBuildDir(Path); InstallDate = ConvertFILETIMEToDateTime(sxsToolset.GetInstallDate()); }
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); }
public static string GetVSPath(string specificVersion = "", bool avoidPrereleases = true, string requiredWorkload = "") { string vsPath = ""; // Method 1 - use "Microsoft.VisualStudio.Setup.Configuration.SetupConfiguration" method. // Note: This code has is a heavily modified version of Heath Stewart's code. // original source: (Heath Stewart, May 2016) https://github.com/microsoft/vs-setup-samples/blob/80426ad4ba10b7901c69ac0fc914317eb65deabf/Setup.Configuration.CS/Program.cs try { var e = new SetupConfiguration().EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { e.Next(1, instances, out fetched); if (fetched > 0) { var instance2 = (ISetupInstance2)instances[0]; var state = instance2.GetState(); // Lets make sure this install is complete. if (state != InstanceState.Complete) { continue; } // If we have a version to match lets make sure to match it. if (!string.IsNullOrWhiteSpace(specificVersion)) { if (!instances[0].GetInstallationVersion().StartsWith(specificVersion)) { continue; } } // If instances[0] is null then skip var catalog = instances[0] as ISetupInstanceCatalog; if (catalog == null) { continue; } // If there is not installation path lets skip if ((state & InstanceState.Local) != InstanceState.Local) { continue; } // Lets make sure it has the required workload - if one was given. if (!string.IsNullOrWhiteSpace(requiredWorkload)) { if ((state & InstanceState.Registered) == InstanceState.Registered) { if (!(from package in instance2.GetPackages() where string.Equals(package.GetType(), "Workload", StringComparison.OrdinalIgnoreCase) where package.GetId().Contains(requiredWorkload) orderby package.GetId() select package).Any()) { continue; } } else { continue; } } // Lets save the installation path and make sure it has a value. vsPath = instance2.GetInstallationPath(); if (string.IsNullOrWhiteSpace(vsPath)) { continue; } // If specified, avoid Pre-release if possible if (avoidPrereleases && catalog.IsPrerelease()) { continue; } // We found the one we need - lets get out of here return(vsPath); } }while (fetched > 0); } catch (Exception) { } if (string.IsNullOrWhiteSpace(vsPath)) { return(vsPath); } // Method 2 - Find the location of visual studio (%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat) // Note: This code has is a heavily modified version of Kevin Kibler's code. // source: (Kevin Kibler, 2014) http://stackoverflow.com/questions/30504/programmatically-retrieve-visual-studio-install-directory List <Version> vsVersions = new List <Version>() { new Version("15.0"), new Version("14.0"), new Version("13.0"), new Version("12.0"), new Version("11.0") }; foreach (var version in vsVersions) { foreach (var isExpress in new bool[] { false, true }) { RegistryKey registryBase32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); RegistryKey vsVersionRegistryKey = registryBase32.OpenSubKey( string.Format(@"{0}\{1}.{2}", (isExpress) ? @"SOFTWARE\Microsoft\VCSExpress" : @"SOFTWARE\Microsoft\VisualStudio", version.Major, version.Minor)); if (vsVersionRegistryKey == null) { continue; } string path = vsVersionRegistryKey.GetValue("InstallDir", string.Empty).ToString(); if (!string.IsNullOrEmpty(path)) { path = Directory.GetParent(path).Parent.Parent.FullName; if (File.Exists(path + @"\VC\bin\cl.exe") && File.Exists(path + @"\VC\vcvarsall.bat")) { vsPath = path; break; } } } if (!string.IsNullOrWhiteSpace(vsPath)) { break; } } return(vsPath); }
/// <summary> /// Gets the installed Visual Studio instances (the first item is the latest version). /// </summary> /// <returns>The install locations.</returns> public static IReadOnlyList <VisualStudioInstance> GetInstances() { if (_installDirs == null) { _installDirs = new List <VisualStudioInstance>(); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { // Visual Studio 2017-2020 List <VisualStudioInstance> preReleaseInstallDirs = null; try { SetupConfiguration setup = new SetupConfiguration(); IEnumSetupInstances enumerator = setup.EnumAllInstances(); ISetupInstance[] instances = new ISetupInstance[1]; while (true) { enumerator.Next(1, instances, out int fetchedCount); if (fetchedCount == 0) { break; } ISetupInstance2 instance = (ISetupInstance2)instances[0]; if ((instance.GetState() & InstanceState.Local) == InstanceState.Local) { VisualStudioVersion version; string displayName = instance.GetDisplayName(); if (displayName.Contains("2019")) { version = VisualStudioVersion.VisualStudio2019; } else if (displayName.Contains("2017")) { version = VisualStudioVersion.VisualStudio2017; } else { throw new Exception(string.Format("Unknown Visual Studio installation. Display name: {0}", displayName)); } var vsInstance = new VisualStudioInstance { Version = version, Path = instance.GetInstallationPath(), }; if (instance is ISetupInstanceCatalog catalog && catalog.IsPrerelease()) { if (preReleaseInstallDirs == null) { preReleaseInstallDirs = new List <VisualStudioInstance>(); } preReleaseInstallDirs.Add(vsInstance); } else { _installDirs.Add(vsInstance); } } } }
public override ImmutableArray<MSBuildInstance> GetInstances() { if (PlatformHelper.IsMono) { return NoInstances; } try { var configuration = Interop.GetSetupConfiguration(); if (configuration == null) { return NoInstances; } var builder = ImmutableArray.CreateBuilder<MSBuildInstance>(); var instanceEnum = configuration.EnumAllInstances(); int fetched; var instances = new ISetupInstance[1]; do { instanceEnum.Next(1, instances, out fetched); if (fetched <= 0) { continue; } var instance = (ISetupInstance2)instances[0]; var state = instance.GetState(); var installVersion = instance.GetInstallationVersion(); var installPath = instance.GetInstallationPath(); if (!Version.TryParse(installVersion, out var version)) { Logger.LogDebug($"Found Visual Studio installation with strange version number: {installVersion} ({installPath})"); continue; } if (state != InstanceState.Complete) { Logger.LogDebug($"Found incomplete Visual Studio installation ({installPath})"); continue; } if (!instance.GetPackages().Any(package => package.GetId() == "Microsoft.VisualStudio.Component.Roslyn.Compiler")) { Logger.LogDebug($"Found Visual Studio installation with no C# package installed ({installPath})"); continue; } var msbuildPath = Path.Combine(installPath, "MSBuild"); var toolsPath = FindMSBuildToolsPath(msbuildPath); if (toolsPath != null) { builder.Add( new MSBuildInstance( instance.GetDisplayName(), toolsPath, version, DiscoveryType.VisualStudioSetup)); } } while (fetched > 0); return builder.ToImmutable(); } catch (COMException ex) { return LogExceptionAndReturnEmpty(ex); } catch (DllNotFoundException ex) { // This is OK, since it probably means that VS 2017 or later isn't installed. // We'll log the exception for debugging though. return LogExceptionAndReturnEmpty(ex); } }