11cb0ef41Sopenharmony_ci// Copyright 2017 - Refael Ackermann
21cb0ef41Sopenharmony_ci// Distributed under MIT style license
31cb0ef41Sopenharmony_ci// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// Usage:
61cb0ef41Sopenharmony_ci// powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
71cb0ef41Sopenharmony_ci// This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciusing System;
101cb0ef41Sopenharmony_ciusing System.Text;
111cb0ef41Sopenharmony_ciusing System.Runtime.InteropServices;
121cb0ef41Sopenharmony_ciusing System.Collections.Generic;
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace VisualStudioConfiguration
151cb0ef41Sopenharmony_ci{
161cb0ef41Sopenharmony_ci    [Flags]
171cb0ef41Sopenharmony_ci    public enum InstanceState : uint
181cb0ef41Sopenharmony_ci    {
191cb0ef41Sopenharmony_ci        None = 0,
201cb0ef41Sopenharmony_ci        Local = 1,
211cb0ef41Sopenharmony_ci        Registered = 2,
221cb0ef41Sopenharmony_ci        NoRebootRequired = 4,
231cb0ef41Sopenharmony_ci        NoErrors = 8,
241cb0ef41Sopenharmony_ci        Complete = 4294967295,
251cb0ef41Sopenharmony_ci    }
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci    [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
281cb0ef41Sopenharmony_ci    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
291cb0ef41Sopenharmony_ci    [ComImport]
301cb0ef41Sopenharmony_ci    public interface IEnumSetupInstances
311cb0ef41Sopenharmony_ci    {
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci        void Next([MarshalAs(UnmanagedType.U4), In] int celt,
341cb0ef41Sopenharmony_ci            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
351cb0ef41Sopenharmony_ci            [MarshalAs(UnmanagedType.U4)] out int pceltFetched);
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci        void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci        void Reset();
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.Interface)]
421cb0ef41Sopenharmony_ci        IEnumSetupInstances Clone();
431cb0ef41Sopenharmony_ci    }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci    [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
461cb0ef41Sopenharmony_ci    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
471cb0ef41Sopenharmony_ci    [ComImport]
481cb0ef41Sopenharmony_ci    public interface ISetupConfiguration
491cb0ef41Sopenharmony_ci    {
501cb0ef41Sopenharmony_ci    }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci    [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
531cb0ef41Sopenharmony_ci    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
541cb0ef41Sopenharmony_ci    [ComImport]
551cb0ef41Sopenharmony_ci    public interface ISetupConfiguration2 : ISetupConfiguration
561cb0ef41Sopenharmony_ci    {
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.Interface)]
591cb0ef41Sopenharmony_ci        IEnumSetupInstances EnumInstances();
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.Interface)]
621cb0ef41Sopenharmony_ci        ISetupInstance GetInstanceForCurrentProcess();
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.Interface)]
651cb0ef41Sopenharmony_ci        ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.Interface)]
681cb0ef41Sopenharmony_ci        IEnumSetupInstances EnumAllInstances();
691cb0ef41Sopenharmony_ci    }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci    [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
721cb0ef41Sopenharmony_ci    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
731cb0ef41Sopenharmony_ci    [ComImport]
741cb0ef41Sopenharmony_ci    public interface ISetupInstance
751cb0ef41Sopenharmony_ci    {
761cb0ef41Sopenharmony_ci    }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci    [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
791cb0ef41Sopenharmony_ci    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
801cb0ef41Sopenharmony_ci    [ComImport]
811cb0ef41Sopenharmony_ci    public interface ISetupInstance2 : ISetupInstance
821cb0ef41Sopenharmony_ci    {
831cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
841cb0ef41Sopenharmony_ci        string GetInstanceId();
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.Struct)]
871cb0ef41Sopenharmony_ci        System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
901cb0ef41Sopenharmony_ci        string GetInstallationName();
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
931cb0ef41Sopenharmony_ci        string GetInstallationPath();
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
961cb0ef41Sopenharmony_ci        string GetInstallationVersion();
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
991cb0ef41Sopenharmony_ci        string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1021cb0ef41Sopenharmony_ci        string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1051cb0ef41Sopenharmony_ci        string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.U4)]
1081cb0ef41Sopenharmony_ci        InstanceState GetState();
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
1111cb0ef41Sopenharmony_ci        ISetupPackageReference[] GetPackages();
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci        ISetupPackageReference GetProduct();
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1161cb0ef41Sopenharmony_ci        string GetProductPath();
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.VariantBool)]
1191cb0ef41Sopenharmony_ci        bool IsLaunchable();
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.VariantBool)]
1221cb0ef41Sopenharmony_ci        bool IsComplete();
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
1251cb0ef41Sopenharmony_ci        ISetupPropertyStore GetProperties();
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1281cb0ef41Sopenharmony_ci        string GetEnginePath();
1291cb0ef41Sopenharmony_ci    }
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci    [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
1321cb0ef41Sopenharmony_ci    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
1331cb0ef41Sopenharmony_ci    [ComImport]
1341cb0ef41Sopenharmony_ci    public interface ISetupPackageReference
1351cb0ef41Sopenharmony_ci    {
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1381cb0ef41Sopenharmony_ci        string GetId();
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1411cb0ef41Sopenharmony_ci        string GetVersion();
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1441cb0ef41Sopenharmony_ci        string GetChip();
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1471cb0ef41Sopenharmony_ci        string GetLanguage();
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1501cb0ef41Sopenharmony_ci        string GetBranch();
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1531cb0ef41Sopenharmony_ci        string GetType();
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.BStr)]
1561cb0ef41Sopenharmony_ci        string GetUniqueId();
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.VariantBool)]
1591cb0ef41Sopenharmony_ci        bool GetIsExtension();
1601cb0ef41Sopenharmony_ci    }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci    [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
1631cb0ef41Sopenharmony_ci    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
1641cb0ef41Sopenharmony_ci    [ComImport]
1651cb0ef41Sopenharmony_ci    public interface ISetupPropertyStore
1661cb0ef41Sopenharmony_ci    {
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
1691cb0ef41Sopenharmony_ci        string[] GetNames();
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci        object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
1721cb0ef41Sopenharmony_ci    }
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci    [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
1751cb0ef41Sopenharmony_ci    [CoClass(typeof(SetupConfigurationClass))]
1761cb0ef41Sopenharmony_ci    [ComImport]
1771cb0ef41Sopenharmony_ci    public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
1781cb0ef41Sopenharmony_ci    {
1791cb0ef41Sopenharmony_ci    }
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci    [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
1821cb0ef41Sopenharmony_ci    [ClassInterface(ClassInterfaceType.None)]
1831cb0ef41Sopenharmony_ci    [ComImport]
1841cb0ef41Sopenharmony_ci    public class SetupConfigurationClass
1851cb0ef41Sopenharmony_ci    {
1861cb0ef41Sopenharmony_ci    }
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci    public static class Main
1891cb0ef41Sopenharmony_ci    {
1901cb0ef41Sopenharmony_ci        public static void PrintJson()
1911cb0ef41Sopenharmony_ci        {
1921cb0ef41Sopenharmony_ci            ISetupConfiguration query = new SetupConfiguration();
1931cb0ef41Sopenharmony_ci            ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
1941cb0ef41Sopenharmony_ci            IEnumSetupInstances e = query2.EnumAllInstances();
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci            int pceltFetched;
1971cb0ef41Sopenharmony_ci            ISetupInstance2[] rgelt = new ISetupInstance2[1];
1981cb0ef41Sopenharmony_ci            List<string> instances = new List<string>();
1991cb0ef41Sopenharmony_ci            while (true)
2001cb0ef41Sopenharmony_ci            {
2011cb0ef41Sopenharmony_ci                e.Next(1, rgelt, out pceltFetched);
2021cb0ef41Sopenharmony_ci                if (pceltFetched <= 0)
2031cb0ef41Sopenharmony_ci                {
2041cb0ef41Sopenharmony_ci                    Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
2051cb0ef41Sopenharmony_ci                    return;
2061cb0ef41Sopenharmony_ci                }
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci                try
2091cb0ef41Sopenharmony_ci                {
2101cb0ef41Sopenharmony_ci                    instances.Add(InstanceJson(rgelt[0]));
2111cb0ef41Sopenharmony_ci                }
2121cb0ef41Sopenharmony_ci                catch (COMException)
2131cb0ef41Sopenharmony_ci                {
2141cb0ef41Sopenharmony_ci                    // Ignore instances that can't be queried.
2151cb0ef41Sopenharmony_ci                }
2161cb0ef41Sopenharmony_ci            }
2171cb0ef41Sopenharmony_ci        }
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci        private static string JsonString(string s)
2201cb0ef41Sopenharmony_ci        {
2211cb0ef41Sopenharmony_ci            return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
2221cb0ef41Sopenharmony_ci        }
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci        private static string InstanceJson(ISetupInstance2 setupInstance2)
2251cb0ef41Sopenharmony_ci        {
2261cb0ef41Sopenharmony_ci            // Visual Studio component directory:
2271cb0ef41Sopenharmony_ci            // https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci            StringBuilder json = new StringBuilder();
2301cb0ef41Sopenharmony_ci            json.Append("{");
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci            string path = JsonString(setupInstance2.GetInstallationPath());
2331cb0ef41Sopenharmony_ci            json.Append(String.Format("\"path\":{0},", path));
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci            string version = JsonString(setupInstance2.GetInstallationVersion());
2361cb0ef41Sopenharmony_ci            json.Append(String.Format("\"version\":{0},", version));
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci            List<string> packages = new List<string>();
2391cb0ef41Sopenharmony_ci            foreach (ISetupPackageReference package in setupInstance2.GetPackages())
2401cb0ef41Sopenharmony_ci            {
2411cb0ef41Sopenharmony_ci                string id = JsonString(package.GetId());
2421cb0ef41Sopenharmony_ci                packages.Add(id);
2431cb0ef41Sopenharmony_ci            }
2441cb0ef41Sopenharmony_ci            json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci            json.Append("}");
2471cb0ef41Sopenharmony_ci            return json.ToString();
2481cb0ef41Sopenharmony_ci        }
2491cb0ef41Sopenharmony_ci    }
2501cb0ef41Sopenharmony_ci}
251