public override string GetVsVersion()
        {
            if (string.IsNullOrEmpty(_vsProductVersion))
            {
                ISetupConfiguration configuration = new SetupConfiguration() as ISetupConfiguration;
                ISetupInstance      instance      = configuration.GetInstanceForCurrentProcess();
                _vsProductVersion = instance.GetInstallationVersion();
            }

            return(_vsProductVersion);
        }
Esempio n. 2
0
        public override string GetVsVersionAndInstance()
        {
            if (string.IsNullOrEmpty(_vsVersionInstance))
            {
                ISetupConfiguration configuration = new SetupConfiguration() as ISetupConfiguration;
                ISetupInstance      instance      = configuration.GetInstanceForCurrentProcess();
                string version    = instance.GetInstallationVersion();
                string instanceId = instance.GetInstanceId();
                _vsVersionInstance = $"{version}-{instanceId}";
            }

            return(_vsVersionInstance);
        }
Esempio n. 3
0
    private static void PrintInstance(ISetupInstance instance, ISetupHelper helper)
    {
        var instance2 = (ISetupInstance2)instance;
        var state     = instance2.GetState();

        Console.WriteLine($"InstanceId: {instance2.GetInstanceId()} ({(state == InstanceState.Complete ? "Complete" : "Incomplete")})");

        var installationVersion = instance.GetInstallationVersion();
        var version             = helper.ParseVersion(installationVersion);

        Console.WriteLine($"InstallationVersion: {installationVersion} ({version})");

        if ((state & InstanceState.Local) == InstanceState.Local)
        {
            Console.WriteLine($"InstallationPath: {instance2.GetInstallationPath()}");
        }

        var catalog = instance as ISetupInstanceCatalog;

        if (catalog != null)
        {
            Console.WriteLine($"IsPrerelease: {catalog.IsPrerelease()}");
        }

        if ((state & InstanceState.Registered) == InstanceState.Registered)
        {
            Console.WriteLine($"Product: {instance2.GetProduct().GetId()}");
            Console.WriteLine("Workloads:");

            PrintWorkloads(instance2.GetPackages());
        }

        var properties = instance2.GetProperties();

        if (properties != null)
        {
            Console.WriteLine("Custom properties:");
            PrintProperties(properties);
        }

        properties = catalog?.GetCatalogInfo();
        if (properties != null)
        {
            Console.WriteLine("Catalog properties:");
            PrintProperties(properties);
        }

        Console.WriteLine();
    }
Esempio n. 4
0
        /// <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);
        }