[6a3a178] | 1 | // Copyright 2017 - Refael Ackermann
|
---|
| 2 | // Distributed under MIT style license
|
---|
| 3 | // See accompanying file LICENSE at https://github.com/node4good/windows-autoconf
|
---|
| 4 |
|
---|
| 5 | // Usage:
|
---|
| 6 | // powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
|
---|
| 7 | // This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.
|
---|
| 8 |
|
---|
| 9 | using System;
|
---|
| 10 | using System.Text;
|
---|
| 11 | using System.Runtime.InteropServices;
|
---|
| 12 | using System.Collections.Generic;
|
---|
| 13 |
|
---|
| 14 | namespace VisualStudioConfiguration
|
---|
| 15 | {
|
---|
| 16 | [Flags]
|
---|
| 17 | public enum InstanceState : uint
|
---|
| 18 | {
|
---|
| 19 | None = 0,
|
---|
| 20 | Local = 1,
|
---|
| 21 | Registered = 2,
|
---|
| 22 | NoRebootRequired = 4,
|
---|
| 23 | NoErrors = 8,
|
---|
| 24 | Complete = 4294967295,
|
---|
| 25 | }
|
---|
| 26 |
|
---|
| 27 | [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
|
---|
| 28 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
---|
| 29 | [ComImport]
|
---|
| 30 | public interface IEnumSetupInstances
|
---|
| 31 | {
|
---|
| 32 |
|
---|
| 33 | void Next([MarshalAs(UnmanagedType.U4), In] int celt,
|
---|
| 34 | [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
|
---|
| 35 | [MarshalAs(UnmanagedType.U4)] out int pceltFetched);
|
---|
| 36 |
|
---|
| 37 | void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
|
---|
| 38 |
|
---|
| 39 | void Reset();
|
---|
| 40 |
|
---|
| 41 | [return: MarshalAs(UnmanagedType.Interface)]
|
---|
| 42 | IEnumSetupInstances Clone();
|
---|
| 43 | }
|
---|
| 44 |
|
---|
| 45 | [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
---|
| 46 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
---|
| 47 | [ComImport]
|
---|
| 48 | public interface ISetupConfiguration
|
---|
| 49 | {
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
|
---|
| 53 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
---|
| 54 | [ComImport]
|
---|
| 55 | public interface ISetupConfiguration2 : ISetupConfiguration
|
---|
| 56 | {
|
---|
| 57 |
|
---|
| 58 | [return: MarshalAs(UnmanagedType.Interface)]
|
---|
| 59 | IEnumSetupInstances EnumInstances();
|
---|
| 60 |
|
---|
| 61 | [return: MarshalAs(UnmanagedType.Interface)]
|
---|
| 62 | ISetupInstance GetInstanceForCurrentProcess();
|
---|
| 63 |
|
---|
| 64 | [return: MarshalAs(UnmanagedType.Interface)]
|
---|
| 65 | ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
|
---|
| 66 |
|
---|
| 67 | [return: MarshalAs(UnmanagedType.Interface)]
|
---|
| 68 | IEnumSetupInstances EnumAllInstances();
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
|
---|
| 72 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
---|
| 73 | [ComImport]
|
---|
| 74 | public interface ISetupInstance
|
---|
| 75 | {
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
|
---|
| 79 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
---|
| 80 | [ComImport]
|
---|
| 81 | public interface ISetupInstance2 : ISetupInstance
|
---|
| 82 | {
|
---|
| 83 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 84 | string GetInstanceId();
|
---|
| 85 |
|
---|
| 86 | [return: MarshalAs(UnmanagedType.Struct)]
|
---|
| 87 | System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
|
---|
| 88 |
|
---|
| 89 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 90 | string GetInstallationName();
|
---|
| 91 |
|
---|
| 92 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 93 | string GetInstallationPath();
|
---|
| 94 |
|
---|
| 95 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 96 | string GetInstallationVersion();
|
---|
| 97 |
|
---|
| 98 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 99 | string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
|
---|
| 100 |
|
---|
| 101 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 102 | string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
|
---|
| 103 |
|
---|
| 104 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 105 | string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
|
---|
| 106 |
|
---|
| 107 | [return: MarshalAs(UnmanagedType.U4)]
|
---|
| 108 | InstanceState GetState();
|
---|
| 109 |
|
---|
| 110 | [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
---|
| 111 | ISetupPackageReference[] GetPackages();
|
---|
| 112 |
|
---|
| 113 | ISetupPackageReference GetProduct();
|
---|
| 114 |
|
---|
| 115 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 116 | string GetProductPath();
|
---|
| 117 |
|
---|
| 118 | [return: MarshalAs(UnmanagedType.VariantBool)]
|
---|
| 119 | bool IsLaunchable();
|
---|
| 120 |
|
---|
| 121 | [return: MarshalAs(UnmanagedType.VariantBool)]
|
---|
| 122 | bool IsComplete();
|
---|
| 123 |
|
---|
| 124 | [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
---|
| 125 | ISetupPropertyStore GetProperties();
|
---|
| 126 |
|
---|
| 127 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 128 | string GetEnginePath();
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 | [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
|
---|
| 132 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
---|
| 133 | [ComImport]
|
---|
| 134 | public interface ISetupPackageReference
|
---|
| 135 | {
|
---|
| 136 |
|
---|
| 137 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 138 | string GetId();
|
---|
| 139 |
|
---|
| 140 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 141 | string GetVersion();
|
---|
| 142 |
|
---|
| 143 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 144 | string GetChip();
|
---|
| 145 |
|
---|
| 146 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 147 | string GetLanguage();
|
---|
| 148 |
|
---|
| 149 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 150 | string GetBranch();
|
---|
| 151 |
|
---|
| 152 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 153 | string GetType();
|
---|
| 154 |
|
---|
| 155 | [return: MarshalAs(UnmanagedType.BStr)]
|
---|
| 156 | string GetUniqueId();
|
---|
| 157 |
|
---|
| 158 | [return: MarshalAs(UnmanagedType.VariantBool)]
|
---|
| 159 | bool GetIsExtension();
|
---|
| 160 | }
|
---|
| 161 |
|
---|
| 162 | [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
|
---|
| 163 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
---|
| 164 | [ComImport]
|
---|
| 165 | public interface ISetupPropertyStore
|
---|
| 166 | {
|
---|
| 167 |
|
---|
| 168 | [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
|
---|
| 169 | string[] GetNames();
|
---|
| 170 |
|
---|
| 171 | object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
|
---|
| 172 | }
|
---|
| 173 |
|
---|
| 174 | [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
---|
| 175 | [CoClass(typeof(SetupConfigurationClass))]
|
---|
| 176 | [ComImport]
|
---|
| 177 | public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
|
---|
| 178 | {
|
---|
| 179 | }
|
---|
| 180 |
|
---|
| 181 | [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
|
---|
| 182 | [ClassInterface(ClassInterfaceType.None)]
|
---|
| 183 | [ComImport]
|
---|
| 184 | public class SetupConfigurationClass
|
---|
| 185 | {
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | public static class Main
|
---|
| 189 | {
|
---|
| 190 | public static void PrintJson()
|
---|
| 191 | {
|
---|
| 192 | ISetupConfiguration query = new SetupConfiguration();
|
---|
| 193 | ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
|
---|
| 194 | IEnumSetupInstances e = query2.EnumAllInstances();
|
---|
| 195 |
|
---|
| 196 | int pceltFetched;
|
---|
| 197 | ISetupInstance2[] rgelt = new ISetupInstance2[1];
|
---|
| 198 | List<string> instances = new List<string>();
|
---|
| 199 | while (true)
|
---|
| 200 | {
|
---|
| 201 | e.Next(1, rgelt, out pceltFetched);
|
---|
| 202 | if (pceltFetched <= 0)
|
---|
| 203 | {
|
---|
| 204 | Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
|
---|
| 205 | return;
|
---|
| 206 | }
|
---|
| 207 |
|
---|
| 208 | try
|
---|
| 209 | {
|
---|
| 210 | instances.Add(InstanceJson(rgelt[0]));
|
---|
| 211 | }
|
---|
| 212 | catch (COMException)
|
---|
| 213 | {
|
---|
| 214 | // Ignore instances that can't be queried.
|
---|
| 215 | }
|
---|
| 216 | }
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 | private static string JsonString(string s)
|
---|
| 220 | {
|
---|
| 221 | return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
---|
| 222 | }
|
---|
| 223 |
|
---|
| 224 | private static string InstanceJson(ISetupInstance2 setupInstance2)
|
---|
| 225 | {
|
---|
| 226 | // Visual Studio component directory:
|
---|
| 227 | // https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
|
---|
| 228 |
|
---|
| 229 | StringBuilder json = new StringBuilder();
|
---|
| 230 | json.Append("{");
|
---|
| 231 |
|
---|
| 232 | string path = JsonString(setupInstance2.GetInstallationPath());
|
---|
| 233 | json.Append(String.Format("\"path\":{0},", path));
|
---|
| 234 |
|
---|
| 235 | string version = JsonString(setupInstance2.GetInstallationVersion());
|
---|
| 236 | json.Append(String.Format("\"version\":{0},", version));
|
---|
| 237 |
|
---|
| 238 | List<string> packages = new List<string>();
|
---|
| 239 | foreach (ISetupPackageReference package in setupInstance2.GetPackages())
|
---|
| 240 | {
|
---|
| 241 | string id = JsonString(package.GetId());
|
---|
| 242 | packages.Add(id);
|
---|
| 243 | }
|
---|
| 244 | json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));
|
---|
| 245 |
|
---|
| 246 | json.Append("}");
|
---|
| 247 | return json.ToString();
|
---|
| 248 | }
|
---|
| 249 | }
|
---|
| 250 | }
|
---|