Find-VS2017.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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 -Version "2.0" -Command "&{Add-Type -Path Find-VS2017.cs; [VisualStudioConfiguration.Main]::Query()}"
  6. using System;
  7. using System.Text;
  8. using System.Runtime.InteropServices;
  9. namespace VisualStudioConfiguration
  10. {
  11. [Flags]
  12. public enum InstanceState : uint
  13. {
  14. None = 0,
  15. Local = 1,
  16. Registered = 2,
  17. NoRebootRequired = 4,
  18. NoErrors = 8,
  19. Complete = 4294967295,
  20. }
  21. [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
  22. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  23. [ComImport]
  24. public interface IEnumSetupInstances
  25. {
  26. void Next([MarshalAs(UnmanagedType.U4), In] int celt,
  27. [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
  28. [MarshalAs(UnmanagedType.U4)] out int pceltFetched);
  29. void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
  30. void Reset();
  31. [return: MarshalAs(UnmanagedType.Interface)]
  32. IEnumSetupInstances Clone();
  33. }
  34. [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
  35. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  36. [ComImport]
  37. public interface ISetupConfiguration
  38. {
  39. }
  40. [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
  41. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  42. [ComImport]
  43. public interface ISetupConfiguration2 : ISetupConfiguration
  44. {
  45. [return: MarshalAs(UnmanagedType.Interface)]
  46. IEnumSetupInstances EnumInstances();
  47. [return: MarshalAs(UnmanagedType.Interface)]
  48. ISetupInstance GetInstanceForCurrentProcess();
  49. [return: MarshalAs(UnmanagedType.Interface)]
  50. ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
  51. [return: MarshalAs(UnmanagedType.Interface)]
  52. IEnumSetupInstances EnumAllInstances();
  53. }
  54. [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
  55. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  56. [ComImport]
  57. public interface ISetupInstance
  58. {
  59. }
  60. [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
  61. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  62. [ComImport]
  63. public interface ISetupInstance2 : ISetupInstance
  64. {
  65. [return: MarshalAs(UnmanagedType.BStr)]
  66. string GetInstanceId();
  67. [return: MarshalAs(UnmanagedType.Struct)]
  68. System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
  69. [return: MarshalAs(UnmanagedType.BStr)]
  70. string GetInstallationName();
  71. [return: MarshalAs(UnmanagedType.BStr)]
  72. string GetInstallationPath();
  73. [return: MarshalAs(UnmanagedType.BStr)]
  74. string GetInstallationVersion();
  75. [return: MarshalAs(UnmanagedType.BStr)]
  76. string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
  77. [return: MarshalAs(UnmanagedType.BStr)]
  78. string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
  79. [return: MarshalAs(UnmanagedType.BStr)]
  80. string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
  81. [return: MarshalAs(UnmanagedType.U4)]
  82. InstanceState GetState();
  83. [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
  84. ISetupPackageReference[] GetPackages();
  85. ISetupPackageReference GetProduct();
  86. [return: MarshalAs(UnmanagedType.BStr)]
  87. string GetProductPath();
  88. [return: MarshalAs(UnmanagedType.VariantBool)]
  89. bool IsLaunchable();
  90. [return: MarshalAs(UnmanagedType.VariantBool)]
  91. bool IsComplete();
  92. [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
  93. ISetupPropertyStore GetProperties();
  94. [return: MarshalAs(UnmanagedType.BStr)]
  95. string GetEnginePath();
  96. }
  97. [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
  98. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  99. [ComImport]
  100. public interface ISetupPackageReference
  101. {
  102. [return: MarshalAs(UnmanagedType.BStr)]
  103. string GetId();
  104. [return: MarshalAs(UnmanagedType.BStr)]
  105. string GetVersion();
  106. [return: MarshalAs(UnmanagedType.BStr)]
  107. string GetChip();
  108. [return: MarshalAs(UnmanagedType.BStr)]
  109. string GetLanguage();
  110. [return: MarshalAs(UnmanagedType.BStr)]
  111. string GetBranch();
  112. [return: MarshalAs(UnmanagedType.BStr)]
  113. string GetType();
  114. [return: MarshalAs(UnmanagedType.BStr)]
  115. string GetUniqueId();
  116. [return: MarshalAs(UnmanagedType.VariantBool)]
  117. bool GetIsExtension();
  118. }
  119. [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
  120. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  121. [ComImport]
  122. public interface ISetupPropertyStore
  123. {
  124. [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
  125. string[] GetNames();
  126. object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
  127. }
  128. [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
  129. [CoClass(typeof(SetupConfigurationClass))]
  130. [ComImport]
  131. public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
  132. {
  133. }
  134. [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
  135. [ClassInterface(ClassInterfaceType.None)]
  136. [ComImport]
  137. public class SetupConfigurationClass
  138. {
  139. }
  140. public static class Main
  141. {
  142. public static void Query()
  143. {
  144. ISetupConfiguration query = new SetupConfiguration();
  145. ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
  146. IEnumSetupInstances e = query2.EnumAllInstances();
  147. int pceltFetched;
  148. ISetupInstance2[] rgelt = new ISetupInstance2[1];
  149. StringBuilder log = new StringBuilder();
  150. while (true)
  151. {
  152. e.Next(1, rgelt, out pceltFetched);
  153. if (pceltFetched <= 0)
  154. {
  155. Console.WriteLine(String.Format("{{\"log\":\"{0}\"}}", log.ToString()));
  156. return;
  157. }
  158. if (CheckInstance(rgelt[0], ref log))
  159. return;
  160. }
  161. }
  162. private static bool CheckInstance(ISetupInstance2 setupInstance2, ref StringBuilder log)
  163. {
  164. // Visual Studio Community 2017 component directory:
  165. // https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads
  166. string path = setupInstance2.GetInstallationPath().Replace("\\", "\\\\");
  167. log.Append(String.Format("Found installation at: {0}\\n", path));
  168. bool hasMSBuild = false;
  169. bool hasVCTools = false;
  170. uint Win10SDKVer = 0;
  171. bool hasWin8SDK = false;
  172. foreach (ISetupPackageReference package in setupInstance2.GetPackages())
  173. {
  174. const string Win10SDKPrefix = "Microsoft.VisualStudio.Component.Windows10SDK.";
  175. string id = package.GetId();
  176. if (id == "Microsoft.VisualStudio.VC.MSBuild.Base")
  177. hasMSBuild = true;
  178. else if (id == "Microsoft.VisualStudio.Component.VC.Tools.x86.x64")
  179. hasVCTools = true;
  180. else if (id.StartsWith(Win10SDKPrefix)) {
  181. string[] parts = id.Substring(Win10SDKPrefix.Length).Split('.');
  182. if (parts.Length > 1 && parts[1] != "Desktop")
  183. continue;
  184. uint foundSdkVer;
  185. if (UInt32.TryParse(parts[0], out foundSdkVer))
  186. Win10SDKVer = Math.Max(Win10SDKVer, foundSdkVer);
  187. } else if (id == "Microsoft.VisualStudio.Component.Windows81SDK")
  188. hasWin8SDK = true;
  189. else
  190. continue;
  191. log.Append(String.Format(" - Found {0}\\n", id));
  192. }
  193. if (!hasMSBuild)
  194. log.Append(" - Missing Visual Studio C++ core features (Microsoft.VisualStudio.VC.MSBuild.Base)\\n");
  195. if (!hasVCTools)
  196. log.Append(" - Missing VC++ 2017 v141 toolset (x86,x64) (Microsoft.VisualStudio.Component.VC.Tools.x86.x64)\\n");
  197. if ((Win10SDKVer == 0) && (!hasWin8SDK))
  198. log.Append(" - Missing a Windows SDK (Microsoft.VisualStudio.Component.Windows10SDK.* or Microsoft.VisualStudio.Component.Windows81SDK)\\n");
  199. if (hasMSBuild && hasVCTools)
  200. {
  201. if (Win10SDKVer > 0)
  202. {
  203. log.Append(" - Using this installation with Windows 10 SDK"/*\\n*/);
  204. Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"10.0.{2}.0\"}}", log.ToString(), path, Win10SDKVer));
  205. return true;
  206. }
  207. else if (hasWin8SDK)
  208. {
  209. log.Append(" - Using this installation with Windows 8.1 SDK"/*\\n*/);
  210. Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"8.1\"}}", log.ToString(), path));
  211. return true;
  212. }
  213. }
  214. log.Append(" - Some required components are missing, not using this installation\\n");
  215. return false;
  216. }
  217. }
  218. }