You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							273 lines
						
					
					
						
							9.3 KiB
						
					
					
				
			
		
		
	
	
							273 lines
						
					
					
						
							9.3 KiB
						
					
					
				// Copyright 2017 - Refael Ackermann | 
						|
// Distributed under MIT style license | 
						|
// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf | 
						|
 | 
						|
// Usage: | 
						|
// powershell -ExecutionPolicy Unrestricted -Version "2.0" -Command "&{Add-Type -Path Find-VS2017.cs; [VisualStudioConfiguration.Main]::Query()}" | 
						|
using System; | 
						|
using System.Text; | 
						|
using System.Runtime.InteropServices; | 
						|
 | 
						|
namespace VisualStudioConfiguration | 
						|
{ | 
						|
    [Flags] | 
						|
    public enum InstanceState : uint | 
						|
    { | 
						|
        None = 0, | 
						|
        Local = 1, | 
						|
        Registered = 2, | 
						|
        NoRebootRequired = 4, | 
						|
        NoErrors = 8, | 
						|
        Complete = 4294967295, | 
						|
    } | 
						|
 | 
						|
    [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] | 
						|
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | 
						|
    [ComImport] | 
						|
    public interface IEnumSetupInstances | 
						|
    { | 
						|
 | 
						|
        void Next([MarshalAs(UnmanagedType.U4), In] int celt, | 
						|
            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, | 
						|
            [MarshalAs(UnmanagedType.U4)] out int pceltFetched); | 
						|
 | 
						|
        void Skip([MarshalAs(UnmanagedType.U4), In] int celt); | 
						|
 | 
						|
        void Reset(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.Interface)] | 
						|
        IEnumSetupInstances Clone(); | 
						|
    } | 
						|
 | 
						|
    [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] | 
						|
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | 
						|
    [ComImport] | 
						|
    public interface ISetupConfiguration | 
						|
    { | 
						|
    } | 
						|
 | 
						|
    [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] | 
						|
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | 
						|
    [ComImport] | 
						|
    public interface ISetupConfiguration2 : ISetupConfiguration | 
						|
    { | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.Interface)] | 
						|
        IEnumSetupInstances EnumInstances(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.Interface)] | 
						|
        ISetupInstance GetInstanceForCurrentProcess(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.Interface)] | 
						|
        ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.Interface)] | 
						|
        IEnumSetupInstances EnumAllInstances(); | 
						|
    } | 
						|
 | 
						|
    [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] | 
						|
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | 
						|
    [ComImport] | 
						|
    public interface ISetupInstance | 
						|
    { | 
						|
    } | 
						|
 | 
						|
    [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] | 
						|
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | 
						|
    [ComImport] | 
						|
    public interface ISetupInstance2 : ISetupInstance | 
						|
    { | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetInstanceId(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.Struct)] | 
						|
        System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetInstallationName(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetInstallationPath(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetInstallationVersion(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.U4)] | 
						|
        InstanceState GetState(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] | 
						|
        ISetupPackageReference[] GetPackages(); | 
						|
 | 
						|
        ISetupPackageReference GetProduct(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetProductPath(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.VariantBool)] | 
						|
        bool IsLaunchable(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.VariantBool)] | 
						|
        bool IsComplete(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] | 
						|
        ISetupPropertyStore GetProperties(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetEnginePath(); | 
						|
    } | 
						|
 | 
						|
    [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] | 
						|
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | 
						|
    [ComImport] | 
						|
    public interface ISetupPackageReference | 
						|
    { | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetId(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetVersion(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetChip(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetLanguage(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetBranch(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetType(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.BStr)] | 
						|
        string GetUniqueId(); | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.VariantBool)] | 
						|
        bool GetIsExtension(); | 
						|
    } | 
						|
 | 
						|
    [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")] | 
						|
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | 
						|
    [ComImport] | 
						|
    public interface ISetupPropertyStore | 
						|
    { | 
						|
 | 
						|
        [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] | 
						|
        string[] GetNames(); | 
						|
 | 
						|
        object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName); | 
						|
    } | 
						|
 | 
						|
    [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] | 
						|
    [CoClass(typeof(SetupConfigurationClass))] | 
						|
    [ComImport] | 
						|
    public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration | 
						|
    { | 
						|
    } | 
						|
 | 
						|
    [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")] | 
						|
    [ClassInterface(ClassInterfaceType.None)] | 
						|
    [ComImport] | 
						|
    public class SetupConfigurationClass | 
						|
    { | 
						|
    } | 
						|
 | 
						|
    public static class Main | 
						|
    { | 
						|
        public static void Query() | 
						|
        { | 
						|
            ISetupConfiguration query = new SetupConfiguration(); | 
						|
            ISetupConfiguration2 query2 = (ISetupConfiguration2)query; | 
						|
            IEnumSetupInstances e = query2.EnumAllInstances(); | 
						|
 | 
						|
            int pceltFetched; | 
						|
            ISetupInstance2[] rgelt = new ISetupInstance2[1]; | 
						|
            StringBuilder log = new StringBuilder(); | 
						|
            while (true) | 
						|
            { | 
						|
                e.Next(1, rgelt, out pceltFetched); | 
						|
                if (pceltFetched <= 0) | 
						|
                { | 
						|
                    Console.WriteLine(String.Format("{{\"log\":\"{0}\"}}", log.ToString())); | 
						|
                    return; | 
						|
                } | 
						|
                if (CheckInstance(rgelt[0], ref log)) | 
						|
                    return; | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        private static bool CheckInstance(ISetupInstance2 setupInstance2, ref StringBuilder log) | 
						|
        { | 
						|
            // Visual Studio Community 2017 component directory: | 
						|
            // https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads | 
						|
 | 
						|
            string path = setupInstance2.GetInstallationPath().Replace("\\", "\\\\"); | 
						|
            log.Append(String.Format("Found installation at: {0}\\n", path)); | 
						|
 | 
						|
            bool hasMSBuild = false; | 
						|
            bool hasVCTools = false; | 
						|
            uint Win10SDKVer = 0; | 
						|
            bool hasWin8SDK = false; | 
						|
 | 
						|
            foreach (ISetupPackageReference package in setupInstance2.GetPackages()) | 
						|
            { | 
						|
                const string Win10SDKPrefix = "Microsoft.VisualStudio.Component.Windows10SDK."; | 
						|
 | 
						|
                string id = package.GetId(); | 
						|
                if (id == "Microsoft.VisualStudio.VC.MSBuild.Base") | 
						|
                    hasMSBuild = true; | 
						|
                else if (id == "Microsoft.VisualStudio.Component.VC.Tools.x86.x64") | 
						|
                    hasVCTools = true; | 
						|
                else if (id.StartsWith(Win10SDKPrefix)) { | 
						|
                    string[] parts = id.Substring(Win10SDKPrefix.Length).Split('.'); | 
						|
                    if (parts.Length > 1 && parts[1] != "Desktop") | 
						|
                        continue; | 
						|
                    uint foundSdkVer; | 
						|
                    if (UInt32.TryParse(parts[0], out foundSdkVer)) | 
						|
                        Win10SDKVer = Math.Max(Win10SDKVer, foundSdkVer); | 
						|
                } else if (id == "Microsoft.VisualStudio.Component.Windows81SDK") | 
						|
                    hasWin8SDK = true; | 
						|
                else | 
						|
                    continue; | 
						|
 | 
						|
                log.Append(String.Format("  - Found {0}\\n", id)); | 
						|
            } | 
						|
 | 
						|
            if (!hasMSBuild) | 
						|
                log.Append("  - Missing Visual Studio C++ core features (Microsoft.VisualStudio.VC.MSBuild.Base)\\n"); | 
						|
            if (!hasVCTools) | 
						|
                log.Append("  - Missing VC++ 2017 v141 toolset (x86,x64) (Microsoft.VisualStudio.Component.VC.Tools.x86.x64)\\n"); | 
						|
            if ((Win10SDKVer == 0) && (!hasWin8SDK)) | 
						|
                log.Append("  - Missing a Windows SDK (Microsoft.VisualStudio.Component.Windows10SDK.* or Microsoft.VisualStudio.Component.Windows81SDK)\\n"); | 
						|
 | 
						|
            if (hasMSBuild && hasVCTools) | 
						|
            { | 
						|
                if (Win10SDKVer > 0) | 
						|
                { | 
						|
                    log.Append("  - Using this installation with Windows 10 SDK"/*\\n*/); | 
						|
                    Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"10.0.{2}.0\"}}", log.ToString(), path, Win10SDKVer)); | 
						|
                    return true; | 
						|
                } | 
						|
                else if (hasWin8SDK) | 
						|
                { | 
						|
                    log.Append("  - Using this installation with Windows 8.1 SDK"/*\\n*/); | 
						|
                    Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"8.1\"}}", log.ToString(), path)); | 
						|
                    return true; | 
						|
                } | 
						|
            } | 
						|
 | 
						|
            log.Append("  - Some required components are missing, not using this installation\\n"); | 
						|
            return false; | 
						|
        } | 
						|
    } | 
						|
}
 | 
						|
 |