|
| 1 | +// Copyright 2017 - Refael Ackermann |
| 2 | +// Distributed under MIT style license |
| 3 | +// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf |
| 4 | +// version: 1.11.2 |
| 5 | + |
| 6 | +// Usage: |
| 7 | +// powershell -ExecutionPolicy Unrestricted -Command "&{ Add-Type -Path GetVS2017Configuration.cs; $insts = [VisualStudioConfiguration.ComSurrogate]::QueryEx(); $insts | ft }" |
| 8 | +namespace VisualStudioConfiguration |
| 9 | +{ |
| 10 | + using System; |
| 11 | + using System.Collections.Generic; |
| 12 | + using System.Runtime.InteropServices; |
| 13 | + using System.Text.RegularExpressions; |
| 14 | + |
| 15 | + [Flags] |
| 16 | + public enum InstanceState : uint |
| 17 | + { |
| 18 | + None = 0, |
| 19 | + Local = 1, |
| 20 | + Registered = 2, |
| 21 | + NoRebootRequired = 4, |
| 22 | + NoErrors = 8, |
| 23 | + Complete = 4294967295, |
| 24 | + } |
| 25 | + |
| 26 | + [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] |
| 27 | + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
| 28 | + [ComImport] |
| 29 | + public interface IEnumSetupInstances |
| 30 | + { |
| 31 | + |
| 32 | + void Next([MarshalAs(UnmanagedType.U4), In] int celt, |
| 33 | + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, |
| 34 | + [MarshalAs(UnmanagedType.U4)] out int pceltFetched); |
| 35 | + |
| 36 | + void Skip([MarshalAs(UnmanagedType.U4), In] int celt); |
| 37 | + |
| 38 | + void Reset(); |
| 39 | + |
| 40 | + [return: MarshalAs(UnmanagedType.Interface)] |
| 41 | + IEnumSetupInstances Clone(); |
| 42 | + } |
| 43 | + |
| 44 | + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] |
| 45 | + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
| 46 | + [ComImport] |
| 47 | + public interface ISetupConfiguration |
| 48 | + { |
| 49 | + } |
| 50 | + |
| 51 | + [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] |
| 52 | + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
| 53 | + [ComImport] |
| 54 | + public interface ISetupConfiguration2 : ISetupConfiguration |
| 55 | + { |
| 56 | + |
| 57 | + [return: MarshalAs(UnmanagedType.Interface)] |
| 58 | + IEnumSetupInstances EnumInstances(); |
| 59 | + |
| 60 | + [return: MarshalAs(UnmanagedType.Interface)] |
| 61 | + ISetupInstance GetInstanceForCurrentProcess(); |
| 62 | + |
| 63 | + [return: MarshalAs(UnmanagedType.Interface)] |
| 64 | + ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path); |
| 65 | + |
| 66 | + [return: MarshalAs(UnmanagedType.Interface)] |
| 67 | + IEnumSetupInstances EnumAllInstances(); |
| 68 | + } |
| 69 | + |
| 70 | + [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] |
| 71 | + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
| 72 | + [ComImport] |
| 73 | + public interface ISetupInstance |
| 74 | + { |
| 75 | + } |
| 76 | + |
| 77 | + [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] |
| 78 | + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
| 79 | + [ComImport] |
| 80 | + public interface ISetupInstance2 : ISetupInstance |
| 81 | + { |
| 82 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 83 | + string GetInstanceId(); |
| 84 | + |
| 85 | + [return: MarshalAs(UnmanagedType.Struct)] |
| 86 | + System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate(); |
| 87 | + |
| 88 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 89 | + string GetInstallationName(); |
| 90 | + |
| 91 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 92 | + string GetInstallationPath(); |
| 93 | + |
| 94 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 95 | + string GetInstallationVersion(); |
| 96 | + |
| 97 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 98 | + string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid); |
| 99 | + |
| 100 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 101 | + string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid); |
| 102 | + |
| 103 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 104 | + string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath); |
| 105 | + |
| 106 | + [return: MarshalAs(UnmanagedType.U4)] |
| 107 | + InstanceState GetState(); |
| 108 | + |
| 109 | + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] |
| 110 | + ISetupPackageReference[] GetPackages(); |
| 111 | + |
| 112 | + ISetupPackageReference GetProduct(); |
| 113 | + |
| 114 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 115 | + string GetProductPath(); |
| 116 | + |
| 117 | + [return: MarshalAs(UnmanagedType.VariantBool)] |
| 118 | + bool IsLaunchable(); |
| 119 | + |
| 120 | + [return: MarshalAs(UnmanagedType.VariantBool)] |
| 121 | + bool IsComplete(); |
| 122 | + |
| 123 | + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] |
| 124 | + ISetupPropertyStore GetProperties(); |
| 125 | + |
| 126 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 127 | + string GetEnginePath(); |
| 128 | + } |
| 129 | + |
| 130 | + [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] |
| 131 | + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
| 132 | + [ComImport] |
| 133 | + public interface ISetupPackageReference |
| 134 | + { |
| 135 | + |
| 136 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 137 | + string GetId(); |
| 138 | + |
| 139 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 140 | + string GetVersion(); |
| 141 | + |
| 142 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 143 | + string GetChip(); |
| 144 | + |
| 145 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 146 | + string GetLanguage(); |
| 147 | + |
| 148 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 149 | + string GetBranch(); |
| 150 | + |
| 151 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 152 | + string GetType(); |
| 153 | + |
| 154 | + [return: MarshalAs(UnmanagedType.BStr)] |
| 155 | + string GetUniqueId(); |
| 156 | + |
| 157 | + [return: MarshalAs(UnmanagedType.VariantBool)] |
| 158 | + bool GetIsExtension(); |
| 159 | + } |
| 160 | + |
| 161 | + [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")] |
| 162 | + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
| 163 | + [ComImport] |
| 164 | + public interface ISetupPropertyStore |
| 165 | + { |
| 166 | + |
| 167 | + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] |
| 168 | + string[] GetNames(); |
| 169 | + |
| 170 | + object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName); |
| 171 | + } |
| 172 | + |
| 173 | + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] |
| 174 | + [CoClass(typeof(SetupConfigurationClass))] |
| 175 | + [ComImport] |
| 176 | + public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration |
| 177 | + { |
| 178 | + } |
| 179 | + |
| 180 | + [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")] |
| 181 | + [ClassInterface(ClassInterfaceType.None)] |
| 182 | + [ComImport] |
| 183 | + public class SetupConfigurationClass |
| 184 | + { |
| 185 | + } |
| 186 | + |
| 187 | + |
| 188 | + public class VSInstance : Dictionary<string, object> |
| 189 | + { |
| 190 | + public object Get(string key) { |
| 191 | + if (!this.ContainsKey(key)) return false; |
| 192 | + return this[key]; |
| 193 | + } |
| 194 | + |
| 195 | + public bool JSONBool(string key) |
| 196 | + { |
| 197 | + if (key == null || key == "") return true; |
| 198 | + if (!this.ContainsKey(key)) return false; |
| 199 | + object val = this[key]; |
| 200 | + if (val is Boolean) return (bool)val; |
| 201 | + if (val is String[]) return ((String[])val).Length != 0; |
| 202 | + string sVal = (string)val; |
| 203 | + if (sVal == null) return false; |
| 204 | + if (sVal.Length == 0) return false; |
| 205 | + if (sVal.Trim() == "{}") return false; |
| 206 | + if (sVal.Trim() == "[]") return false; |
| 207 | + if (sVal.Trim() == "0") return false; |
| 208 | + return true; |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + public static class ComSurrogate |
| 213 | + { |
| 214 | + public static bool Is64() |
| 215 | + { |
| 216 | + return (IntPtr.Size == 8); |
| 217 | + } |
| 218 | + |
| 219 | + public static List<VSInstance> QueryEx(params string[] args) |
| 220 | + { |
| 221 | + List<VSInstance> insts = new List<VSInstance>(); |
| 222 | + ISetupConfiguration query = new SetupConfiguration(); |
| 223 | + ISetupConfiguration2 query2 = (ISetupConfiguration2) query; |
| 224 | + IEnumSetupInstances e = query2.EnumAllInstances(); |
| 225 | + ISetupInstance2[] rgelt = new ISetupInstance2[1]; |
| 226 | + int pceltFetched; |
| 227 | + e.Next(1, rgelt, out pceltFetched); |
| 228 | + while (pceltFetched > 0) |
| 229 | + { |
| 230 | + ISetupInstance2 raw = rgelt[0]; |
| 231 | + insts.Add(ParseInstance(raw)); |
| 232 | + e.Next(1, rgelt, out pceltFetched); |
| 233 | + } |
| 234 | + foreach (VSInstance inst in insts.ToArray()) |
| 235 | + { |
| 236 | + foreach (string key in args) { |
| 237 | + if (!inst.JSONBool(key)) { |
| 238 | + insts.Remove(inst); |
| 239 | + } |
| 240 | + } |
| 241 | + if (Array.IndexOf(args, "Packages") == -1) { |
| 242 | + inst.Remove("Packages"); |
| 243 | + } |
| 244 | + } |
| 245 | + return insts; |
| 246 | + } |
| 247 | + |
| 248 | + private static VSInstance ParseInstance(ISetupInstance2 setupInstance2) |
| 249 | + { |
| 250 | + VSInstance inst = new VSInstance(); |
| 251 | + string[] prodParts = setupInstance2.GetProduct().GetId().Split('.'); |
| 252 | + Array.Reverse(prodParts); |
| 253 | + inst["Product"] = prodParts[0]; |
| 254 | + inst["ID"] = setupInstance2.GetInstanceId(); |
| 255 | + inst["Name"] = setupInstance2.GetDisplayName(0x1000); |
| 256 | + inst["Description"] = setupInstance2.GetDescription(0x1000); |
| 257 | + inst["InstallationName"] = setupInstance2.GetInstallationName(); |
| 258 | + inst["Version"] = setupInstance2.GetInstallationVersion(); |
| 259 | + inst["State"] = Enum.GetName(typeof(InstanceState), setupInstance2.GetState()); |
| 260 | + inst["InstallationPath"] = setupInstance2.GetInstallationPath(); |
| 261 | + inst["IsComplete"] = setupInstance2.IsComplete(); |
| 262 | + inst["IsLaunchable"] = setupInstance2.IsLaunchable(); |
| 263 | + inst["Common7ToolsPath"] = inst["InstallationPath"] + @"\Common7\Tools\"; |
| 264 | + inst["CmdPath"] = inst["Common7ToolsPath"] + "VsDevCmd.bat"; |
| 265 | + inst["VCAuxiliaryBuildPath"] = inst["InstallationPath"] + @"\VC\Auxiliary\Build\"; |
| 266 | + inst["VCVarsAllPath"] = inst["VCAuxiliaryBuildPath"] + "vcvarsall.bat"; |
| 267 | + |
| 268 | + inst["Win8SDK"] = ""; |
| 269 | + inst["SDK10Full"] = ""; |
| 270 | + inst["VisualCppTools"] = ""; |
| 271 | + |
| 272 | + Regex trimmer = new Regex(@"\.\d+$"); |
| 273 | + |
| 274 | + List<string> packs = new List<String>(); |
| 275 | + foreach (ISetupPackageReference package in setupInstance2.GetPackages()) |
| 276 | + { |
| 277 | + string id = package.GetId(); |
| 278 | + |
| 279 | + string ver = package.GetVersion(); |
| 280 | + string detail = "{\"id\": \"" + id + "\", \"version\":\"" + ver + "\"}"; |
| 281 | + packs.Add(" " + detail); |
| 282 | + |
| 283 | + if (id.Contains("Component.MSBuild")) { |
| 284 | + inst["MSBuild"] = detail; |
| 285 | + inst["MSBuildVerFull"] = ver; |
| 286 | + } else if (id.Contains("Microsoft.VisualCpp.Tools.Core")) { |
| 287 | + inst["VCTools"] = detail; |
| 288 | + inst["VisualCppToolsFullVersion"] = ver; |
| 289 | + string majorMinor = trimmer.Replace(trimmer.Replace(ver, ""), ""); |
| 290 | + inst["VisualCppToolsVersionMinor"] = majorMinor; |
| 291 | + inst["VCToolsVersionCode"] = "vc" + majorMinor.Replace(".", ""); |
| 292 | + } else if (id.Contains("Microsoft.Windows.81SDK")) { |
| 293 | + if (inst["Win8SDK"].ToString().CompareTo(ver) > 0) continue; |
| 294 | + inst["Win8SDK"] = ver; |
| 295 | + } else if (id.Contains("Win10SDK_10")) { |
| 296 | + if (inst["SDK10Full"].ToString().CompareTo(ver) > 0) continue; |
| 297 | + inst["SDK10Full"] = ver; |
| 298 | + } |
| 299 | + } |
| 300 | + packs.Sort(); |
| 301 | + inst["Packages"] = packs.ToArray(); |
| 302 | + |
| 303 | + string[] sdk10Parts = inst["SDK10Full"].ToString().Split('.'); |
| 304 | + sdk10Parts[sdk10Parts.Length - 1] = "0"; |
| 305 | + inst["SDK10"] = String.Join(".", sdk10Parts); |
| 306 | + inst["SDK"] = inst["SDK10"].ToString() != "0" ? inst["SDK10"] : inst["Win8SDK"]; |
| 307 | + if (inst.ContainsKey("MSBuildVerFull")) { |
| 308 | + string ver = trimmer.Replace(trimmer.Replace((string)inst["MSBuildVerFull"], ""), ""); |
| 309 | + inst["MSBuildVer"] = ver; |
| 310 | + inst["MSBuildToolsPath"] = inst["InstallationPath"] + @"\MSBuild\" + ver + @"\Bin\"; |
| 311 | + inst["MSBuildPath"] = inst["MSBuildToolsPath"] + "MSBuild.exe"; |
| 312 | + } |
| 313 | + if (inst.ContainsKey("VCTools")) { |
| 314 | + string ver = trimmer.Replace((string)inst["VisualCppToolsFullVersion"], ""); |
| 315 | + inst["VisualCppToolsX64"] = inst["InstallationPath"] + @"\VC\Tools\MSVC\" + ver + @"\bin\HostX64\x64\"; |
| 316 | + inst["VisualCppToolsX64CL"] = inst["VisualCppToolsX64"] + "cl.exe"; |
| 317 | + inst["VisualCppToolsX86"] = inst["InstallationPath"] + @"\VC\Tools\MSVC\" + ver + @"\bin\HostX86\x86\"; |
| 318 | + inst["VisualCppToolsX86CL"] = inst["VisualCppToolsX86"] + "cl.exe"; |
| 319 | + inst["VisualCppTools"] = Is64() ? inst["VisualCppToolsX64"] : inst["VisualCppToolsX86"]; |
| 320 | + inst["VisualCppToolsCL"] = Is64() ? inst["VisualCppToolsX64CL"] : inst["VisualCppToolsX86CL"]; |
| 321 | + } |
| 322 | + inst["IsVcCompatible"] = inst.JSONBool("SDK") && inst.JSONBool("MSBuild") && inst.JSONBool("VisualCppTools"); |
| 323 | + return inst; |
| 324 | + } |
| 325 | + } |
| 326 | +} |
0 commit comments