Find-VisualStudio.cs 7.7 KB

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