|
|
@ -1,12 +1,8 @@ |
|
|
|
using System; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Globalization; |
|
|
|
using System.Globalization; |
|
|
|
using System.IO; |
|
|
|
|
|
|
|
using System.Linq; |
|
|
|
|
|
|
|
using System.Text.RegularExpressions; |
|
|
|
using System.Text.RegularExpressions; |
|
|
|
using Microsoft.Win32; |
|
|
|
using Microsoft.Win32; |
|
|
|
using Microsoft.VisualStudio.Setup.Configuration; |
|
|
|
|
|
|
|
using System.Runtime.InteropServices; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace CppSharp |
|
|
|
namespace CppSharp |
|
|
|
{ |
|
|
|
{ |
|
|
@ -50,35 +46,6 @@ namespace CppSharp |
|
|
|
|
|
|
|
|
|
|
|
public static class MSVCToolchain |
|
|
|
public static class MSVCToolchain |
|
|
|
{ |
|
|
|
{ |
|
|
|
/// <summary>Dumps the detected SDK versions.</summary>
|
|
|
|
|
|
|
|
public static void DumpSdks() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<ToolchainVersion> vsSdks = GetVisualStudioSdks(); |
|
|
|
|
|
|
|
DumpSdks("Visual Studio", vsSdks); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ToolchainVersion> windowsSdks = GetWindowsSdks(); |
|
|
|
|
|
|
|
DumpSdks("Windows", windowsSdks); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ToolchainVersion> windowsKitsSdks = GetWindowsKitsSdks(); |
|
|
|
|
|
|
|
DumpSdks("Windows Kits", windowsKitsSdks); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ToolchainVersion> netFrameworkSdks = GetNetFrameworkSdks(); |
|
|
|
|
|
|
|
DumpSdks(".NET Framework", netFrameworkSdks); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ToolchainVersion> msbuildSdks = GetMSBuildSdks(); |
|
|
|
|
|
|
|
DumpSdks("MSBuild", msbuildSdks); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>Dumps include directories for selected toolchain.</summary>
|
|
|
|
|
|
|
|
/// <param name="vsVersion">The version of Visual Studio to dump the SDK-s of.</param>
|
|
|
|
|
|
|
|
public static void DumpSdkIncludes(VisualStudioVersion vsVersion = |
|
|
|
|
|
|
|
VisualStudioVersion.Latest) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Console.WriteLine("\nInclude search path (VS: {0}):", vsVersion); |
|
|
|
|
|
|
|
foreach (var include in MSVCToolchain.GetSystemIncludes(vsVersion)) |
|
|
|
|
|
|
|
Console.WriteLine($"\t{include}"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Version GetCLVersion(VisualStudioVersion vsVersion) |
|
|
|
public static Version GetCLVersion(VisualStudioVersion vsVersion) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Version clVersion; |
|
|
|
Version clVersion; |
|
|
@ -104,247 +71,6 @@ namespace CppSharp |
|
|
|
return clVersion; |
|
|
|
return clVersion; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static ToolchainVersion GetVSToolchain(VisualStudioVersion vsVersion) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (VSSdks.Value.Count == 0) |
|
|
|
|
|
|
|
throw new Exception("Could not find a valid Visual Studio toolchain"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (vsVersion == VisualStudioVersion.Latest) |
|
|
|
|
|
|
|
? VSSdks.Value.Last() |
|
|
|
|
|
|
|
: VSSdks.Value.Find(version => |
|
|
|
|
|
|
|
(int) version.Version == GetVisualStudioVersion(vsVersion)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static ToolchainVersion GetWindowsKitsToolchain(VisualStudioVersion vsVersion, |
|
|
|
|
|
|
|
out int windowsSdkMajorVer) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var vsSdk = GetVSToolchain(vsVersion); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var vsDir = vsSdk.Directory; |
|
|
|
|
|
|
|
vsDir = vsDir.Substring(0, vsDir.LastIndexOf(@"\Common7\IDE", |
|
|
|
|
|
|
|
StringComparison.Ordinal)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check VCVarsQueryRegistry.bat to see which Windows SDK version
|
|
|
|
|
|
|
|
// is supposed to be used with this VS version.
|
|
|
|
|
|
|
|
var vcVarsPath = Path.Combine(vsDir, @"Common7\Tools\VCVarsQueryRegistry.bat"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
windowsSdkMajorVer = 0; |
|
|
|
|
|
|
|
string kitsRootKey = string.Empty; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var vcVarsFile = File.ReadAllText(vcVarsPath); |
|
|
|
|
|
|
|
var match = Regex.Match(vcVarsFile, @"Windows\\v([1-9][0-9]*)\.?([0-9]*)"); |
|
|
|
|
|
|
|
if (match.Success) |
|
|
|
|
|
|
|
windowsSdkMajorVer = int.Parse(match.Groups[1].Value); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match = Regex.Match(vcVarsFile, "KitsRoot([1-9][0-9]*)"); |
|
|
|
|
|
|
|
if (match.Success) |
|
|
|
|
|
|
|
kitsRootKey = match.Groups[0].Value; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ToolchainVersion> windowsKitsSdks = GetWindowsKitsSdks(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var windowsKitSdk = (!string.IsNullOrWhiteSpace(kitsRootKey)) |
|
|
|
|
|
|
|
? windowsKitsSdks.Find(version => version.Value == kitsRootKey) |
|
|
|
|
|
|
|
: windowsKitsSdks.Last(); |
|
|
|
|
|
|
|
// If for some reason we cannot find the SDK version reported by VS
|
|
|
|
|
|
|
|
// in the system, then fallback to the latest version found.
|
|
|
|
|
|
|
|
if (windowsKitSdk.Value == null) |
|
|
|
|
|
|
|
windowsKitSdk = windowsKitsSdks.Last(); |
|
|
|
|
|
|
|
return windowsKitSdk; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static VisualStudioVersion FindVSVersion(VisualStudioVersion vsVersion) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (vsVersion != VisualStudioVersion.Latest) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var vsSdk = GetVSToolchain(vsVersion); |
|
|
|
|
|
|
|
if (vsSdk.IsValid) |
|
|
|
|
|
|
|
return vsVersion; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// we don't know what "latest" is on a given machine
|
|
|
|
|
|
|
|
// so start from the latest specified version and loop until a match is found
|
|
|
|
|
|
|
|
for (var i = VisualStudioVersion.Latest - 1; i >= VisualStudioVersion.VS2012; i--) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vsVersion = FindVSVersion(i); |
|
|
|
|
|
|
|
if (vsVersion != VisualStudioVersion.Latest) |
|
|
|
|
|
|
|
return vsVersion; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return VisualStudioVersion.Latest; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>Gets the system include folders for the given Visual Studio version.</summary>
|
|
|
|
|
|
|
|
/// <param name="vsVersion">The version of Visual Studio to get
|
|
|
|
|
|
|
|
/// system includes from.</param>
|
|
|
|
|
|
|
|
public static List<string> GetSystemIncludes(VisualStudioVersion vsVersion) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var vsSdk = GetVSToolchain(vsVersion); |
|
|
|
|
|
|
|
var vsDir = vsSdk.Directory; |
|
|
|
|
|
|
|
if (Path.GetFileName(vsDir) == "IDE") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
string secondToLastDirPath = Path.GetDirectoryName(vsDir); |
|
|
|
|
|
|
|
if (Path.GetFileName(secondToLastDirPath) == "Common7") |
|
|
|
|
|
|
|
vsDir = Path.GetDirectoryName(secondToLastDirPath); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return GetSystemIncludes(vsVersion, vsDir); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void DumpSdks(string sku, IEnumerable<ToolchainVersion> sdks) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Console.WriteLine("\n{0} SDKs:", sku); |
|
|
|
|
|
|
|
foreach (var sdk in sdks) |
|
|
|
|
|
|
|
Console.WriteLine("\t({0}) {1}", sdk.Version, sdk.Directory); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static int GetVisualStudioVersion(VisualStudioVersion version) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
switch (version) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case VisualStudioVersion.VS2012: |
|
|
|
|
|
|
|
return 11; |
|
|
|
|
|
|
|
case VisualStudioVersion.VS2013: |
|
|
|
|
|
|
|
return 12; |
|
|
|
|
|
|
|
case VisualStudioVersion.VS2015: |
|
|
|
|
|
|
|
return 14; |
|
|
|
|
|
|
|
case VisualStudioVersion.VS2017: |
|
|
|
|
|
|
|
case VisualStudioVersion.Latest: |
|
|
|
|
|
|
|
return 15; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new Exception("Unknown Visual Studio version"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static List<string> GetSystemIncludes(VisualStudioVersion vsVersion, string vsDir) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (vsVersion == VisualStudioVersion.VS2017) |
|
|
|
|
|
|
|
return GetSystemIncludesVS2017(vsDir); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int windowsSdkMajorVer; |
|
|
|
|
|
|
|
var windowsKitSdk = GetWindowsKitsToolchain(vsVersion, out windowsSdkMajorVer); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ToolchainVersion> windowsSdks = GetWindowsSdks(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var includes = new List<string> { Path.Combine(vsDir, @"VC\include") }; |
|
|
|
|
|
|
|
// Older Visual Studio versions provide their own Windows SDK.
|
|
|
|
|
|
|
|
if (windowsSdks.Count == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
includes.Add(Path.Combine(vsDir, @"\VC\PlatformSDK\Include")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
includes.AddRange(GetIncludeDirsFromWindowsSdks(windowsSdkMajorVer, windowsSdks)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes.AddRange( |
|
|
|
|
|
|
|
CollectUniversalCRuntimeIncludeDirs(vsDir, windowsKitSdk, windowsSdkMajorVer)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return includes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<string> GetIncludeDirsFromWindowsSdks( |
|
|
|
|
|
|
|
int windowsSdkMajorVer, List<ToolchainVersion> windowsSdks) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var majorWindowsSdk = windowsSdks.Find( |
|
|
|
|
|
|
|
version => (int) Math.Floor(version.Version) == windowsSdkMajorVer); |
|
|
|
|
|
|
|
var windowsSdkDirs = majorWindowsSdk.Directory != null ? |
|
|
|
|
|
|
|
new[] { majorWindowsSdk.Directory } : |
|
|
|
|
|
|
|
windowsSdks.Select(w => w.Directory).Reverse(); |
|
|
|
|
|
|
|
foreach (var windowsSdkDir in windowsSdkDirs) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (windowsSdkMajorVer >= 8) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var windowsSdkIncludeDir = Path.Combine(windowsSdkDir, "include"); |
|
|
|
|
|
|
|
IEnumerable<string> searchDirs = new[] { windowsSdkIncludeDir }; |
|
|
|
|
|
|
|
if (Directory.Exists(windowsSdkIncludeDir)) |
|
|
|
|
|
|
|
searchDirs = searchDirs.Union(Directory.EnumerateDirectories(windowsSdkIncludeDir)); |
|
|
|
|
|
|
|
foreach (var dir in searchDirs) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var shared = Path.Combine(dir, "shared"); |
|
|
|
|
|
|
|
var um = Path.Combine(dir, "um"); |
|
|
|
|
|
|
|
var winrt = Path.Combine(dir, "winrt"); |
|
|
|
|
|
|
|
if (Directory.Exists(shared) && Directory.Exists(um) && |
|
|
|
|
|
|
|
Directory.Exists(winrt)) |
|
|
|
|
|
|
|
return new[] { shared, um, winrt }; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var include = Path.Combine(windowsSdkDir, "include"); |
|
|
|
|
|
|
|
if (Directory.Exists(include)) |
|
|
|
|
|
|
|
return new[] { include }; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return new string[0]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<string> CollectUniversalCRuntimeIncludeDirs( |
|
|
|
|
|
|
|
string vsDir, ToolchainVersion windowsKitSdk, int windowsSdkMajorVer) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var includes = new List<string>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check vsvars32.bat to see location of the new Universal C runtime library.
|
|
|
|
|
|
|
|
string ucrtPaths = string.Empty; |
|
|
|
|
|
|
|
var vsVarsPath = Path.Combine(vsDir, @"Common7\Tools\vsvars32.bat"); |
|
|
|
|
|
|
|
if (File.Exists(vsVarsPath)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var vsVarsFile = File.ReadAllText(vsVarsPath); |
|
|
|
|
|
|
|
var match = Regex.Match(vsVarsFile, "INCLUDE=%UniversalCRTSdkDir%(.+)%INCLUDE%"); |
|
|
|
|
|
|
|
if (match.Success) |
|
|
|
|
|
|
|
ucrtPaths = match.Groups[1].Value; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(ucrtPaths)) return includes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// like the rest of GetSystemIncludes, this is a hack
|
|
|
|
|
|
|
|
// which copies the logic in the vcvarsqueryregistry.bat
|
|
|
|
|
|
|
|
// the correct way would be to execute the script and collect the values
|
|
|
|
|
|
|
|
// there's a reference implementation in the 'get_MSVC_UCRTVersion_from_VS_batch_script' branch
|
|
|
|
|
|
|
|
// however, it cannot be used because it needs invoking an external process to run the .bat
|
|
|
|
|
|
|
|
// which is killed prematurely by VS when the pre-build events of wrapper projects are run
|
|
|
|
|
|
|
|
const string ucrtVersionEnvVar = "%UCRTVersion%"; |
|
|
|
|
|
|
|
foreach (var splitPath in ucrtPaths.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var path = splitPath.TrimStart('\\'); |
|
|
|
|
|
|
|
var index = path.IndexOf(ucrtVersionEnvVar, StringComparison.Ordinal); |
|
|
|
|
|
|
|
if (index >= 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var include = path.Substring(0, index); |
|
|
|
|
|
|
|
var parentIncludeDir = Path.Combine(windowsKitSdk.Directory, include); |
|
|
|
|
|
|
|
var dirPrefix = windowsSdkMajorVer + "."; |
|
|
|
|
|
|
|
var includeDir = |
|
|
|
|
|
|
|
(from dir in Directory.EnumerateDirectories(parentIncludeDir).OrderByDescending(d => d) |
|
|
|
|
|
|
|
where Path.GetFileName(dir).StartsWith(dirPrefix, StringComparison.Ordinal) |
|
|
|
|
|
|
|
select Path.Combine(windowsKitSdk.Directory, include, dir)).FirstOrDefault(); |
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(includeDir)) |
|
|
|
|
|
|
|
includes.Add(Path.Combine(includeDir, Path.GetFileName(path))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
includes.Add(Path.Combine(windowsKitSdk.Directory, path)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return includes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Gets .NET framework installation directories.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <returns>Success of the operation</returns>
|
|
|
|
|
|
|
|
public static List<ToolchainVersion> GetNetFrameworkSdks() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<ToolchainVersion> versions = GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\.NETFramework", |
|
|
|
|
|
|
|
"InstallRoot", RegistryView.Registry32); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (versions.Count == 0 && Environment.Is64BitProcess) |
|
|
|
|
|
|
|
versions.AddRange(GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\.NETFramework", |
|
|
|
|
|
|
|
"InstallRoot", RegistryView.Registry64)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
versions.Sort((v1, v2) => (int)(v1.Version - v2.Version)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return versions; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Gets MSBuild installation directories.
|
|
|
|
/// Gets MSBuild installation directories.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
@ -366,130 +92,6 @@ namespace CppSharp |
|
|
|
return versions; |
|
|
|
return versions; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Gets Windows SDK installation directories.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <returns>Success of the operation</returns>
|
|
|
|
|
|
|
|
public static List<ToolchainVersion> GetWindowsSdks() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<ToolchainVersion> versions = GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", |
|
|
|
|
|
|
|
"InstallationFolder", RegistryView.Registry32); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (versions.Count == 0 && Environment.Is64BitProcess) |
|
|
|
|
|
|
|
versions.AddRange(GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", |
|
|
|
|
|
|
|
"InstallationFolder", RegistryView.Registry64)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
versions.Sort((v1, v2) => (int)(v1.Version - v2.Version)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return versions; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Gets Windows Kits SDK installation directories.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <returns>Success of the operation</returns>
|
|
|
|
|
|
|
|
public static List<ToolchainVersion> GetWindowsKitsSdks() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<ToolchainVersion> versions = GetToolchainsFromSystemRegistryValues( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", |
|
|
|
|
|
|
|
"KitsRoot", RegistryView.Registry32); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (versions.Count == 0 && Environment.Is64BitProcess) |
|
|
|
|
|
|
|
versions.AddRange(GetToolchainsFromSystemRegistryValues( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", |
|
|
|
|
|
|
|
"KitsRoot", RegistryView.Registry64)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
versions.Sort((v1, v2) => (int)(v1.Version - v2.Version)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return versions; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Gets Visual Studio installation directories.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="versions">Collection holding information about available Visual Studio instances</param>
|
|
|
|
|
|
|
|
/// <returns>Success of the operation</returns>
|
|
|
|
|
|
|
|
public static List<ToolchainVersion> GetVisualStudioSdks() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var versions = GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio", |
|
|
|
|
|
|
|
"InstallDir", RegistryView.Registry32); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (versions.Count == 0 && Environment.Is64BitProcess) |
|
|
|
|
|
|
|
versions.AddRange(GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio", |
|
|
|
|
|
|
|
"InstallDir", RegistryView.Registry64)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
versions.AddRange(GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress", |
|
|
|
|
|
|
|
"InstallDir", RegistryView.Registry32)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (versions.Count == 0 && Environment.Is64BitProcess) |
|
|
|
|
|
|
|
versions.AddRange(GetToolchainsFromSystemRegistry( |
|
|
|
|
|
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress", |
|
|
|
|
|
|
|
"InstallDir", RegistryView.Registry64)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Check for VS 2017
|
|
|
|
|
|
|
|
GetVs2017Instances(versions); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
versions.Sort((v1, v2) => (int)(v1.Version - v2.Version)); |
|
|
|
|
|
|
|
return versions; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Read registry strings looking for matching values.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="keyPath">The path to the key in the registry.</param>
|
|
|
|
|
|
|
|
/// <param name="matchValue">The value to match in the located key, if any.</param>
|
|
|
|
|
|
|
|
/// <param name="view">The type of registry, 32 or 64, to target.</param>
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
public static List<ToolchainVersion> GetToolchainsFromSystemRegistryValues( |
|
|
|
|
|
|
|
string keyPath, string matchValue, RegistryView view) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
string subKey; |
|
|
|
|
|
|
|
var hive = GetRegistryHive(keyPath, out subKey); |
|
|
|
|
|
|
|
using (var rootKey = RegistryKey.OpenBaseKey(hive, view)) |
|
|
|
|
|
|
|
using (var key = rootKey.OpenSubKey(subKey, writable: false)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var entries = new List<ToolchainVersion>(); |
|
|
|
|
|
|
|
if (key == null) |
|
|
|
|
|
|
|
return entries; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var valueName in key.GetValueNames()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!valueName.Contains(matchValue)) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var value = key.GetValue(valueName) as string; |
|
|
|
|
|
|
|
if (value == null) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float version = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get the number version from the key value.
|
|
|
|
|
|
|
|
var match = Regex.Match(value, @".*([1-9][0-9]*\.?[0-9]*)"); |
|
|
|
|
|
|
|
if (match.Success) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
float.TryParse(match.Groups[1].Value, NumberStyles.Number, |
|
|
|
|
|
|
|
CultureInfo.InvariantCulture, out version); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var entry = new ToolchainVersion |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Directory = value, |
|
|
|
|
|
|
|
Version = version, |
|
|
|
|
|
|
|
Value = valueName |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
entries.Add(entry); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return entries; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Read registry string.
|
|
|
|
/// Read registry string.
|
|
|
|
/// This also supports a means to look for high-versioned keys by use
|
|
|
|
/// This also supports a means to look for high-versioned keys by use
|
|
|
@ -591,166 +193,5 @@ namespace CppSharp |
|
|
|
|
|
|
|
|
|
|
|
return hive; |
|
|
|
return hive; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static Lazy<List<ToolchainVersion>> VSSdks = |
|
|
|
|
|
|
|
new Lazy<List<ToolchainVersion>>(GetVisualStudioSdks, true); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region VS2017
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Returns all system includes of the installed VS 2017 instance.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="vsDir">Path to the visual studio installation (for identifying the correct instance)</param>
|
|
|
|
|
|
|
|
/// <returns>The system includes</returns>
|
|
|
|
|
|
|
|
private static List<string> GetSystemIncludesVS2017(string vsDir) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<string> includes = new List<string>(); |
|
|
|
|
|
|
|
//They includes are in a different folder
|
|
|
|
|
|
|
|
const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154); |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var query = new SetupConfiguration(); |
|
|
|
|
|
|
|
var query2 = (ISetupConfiguration2) query; |
|
|
|
|
|
|
|
var e = query2.EnumAllInstances(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int fetched; |
|
|
|
|
|
|
|
var instances = new ISetupInstance[1]; |
|
|
|
|
|
|
|
var regexWinSDK10Version = new Regex(@"Windows10SDK\.(\d+)\.?"); |
|
|
|
|
|
|
|
do |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
e.Next(1, instances, out fetched); |
|
|
|
|
|
|
|
if (fetched > 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var instance = (ISetupInstance2) instances[0]; |
|
|
|
|
|
|
|
if (instance.GetInstallationPath() != vsDir) continue; |
|
|
|
|
|
|
|
var packages = instance.GetPackages(); |
|
|
|
|
|
|
|
var vc_tools = from package in packages |
|
|
|
|
|
|
|
where package.GetId().Contains("Microsoft.VisualStudio.Component.VC.Tools") |
|
|
|
|
|
|
|
orderby package.GetId() |
|
|
|
|
|
|
|
select package; |
|
|
|
|
|
|
|
if (vc_tools.Any()) |
|
|
|
|
|
|
|
{ // Tools found, get path
|
|
|
|
|
|
|
|
var path = instance.GetInstallationPath(); |
|
|
|
|
|
|
|
var versionFilePath = path + @"\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"; |
|
|
|
|
|
|
|
var version = System.IO.File.ReadLines(versionFilePath).ElementAt(0).Trim(); |
|
|
|
|
|
|
|
includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\include"); |
|
|
|
|
|
|
|
includes.Add(path + @"\VC\Tools\MSVC\" + version + @"\atlmfc\include"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var sdks = from package in packages |
|
|
|
|
|
|
|
where package.GetId().Contains("Windows10SDK") || |
|
|
|
|
|
|
|
package.GetId().Contains("Windows81SDK") || |
|
|
|
|
|
|
|
package.GetId().Contains("Win10SDK_10") |
|
|
|
|
|
|
|
select package; |
|
|
|
|
|
|
|
var win10sdks = from sdk in sdks |
|
|
|
|
|
|
|
where regexWinSDK10Version.Match(sdk.GetId()).Success |
|
|
|
|
|
|
|
orderby sdk.GetId() |
|
|
|
|
|
|
|
select sdk; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var win8sdks = from sdk in sdks |
|
|
|
|
|
|
|
where sdk.GetId().Contains("Windows81SDK") |
|
|
|
|
|
|
|
select sdk; |
|
|
|
|
|
|
|
if (win10sdks.Any()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var sdk = win10sdks.Last(); |
|
|
|
|
|
|
|
var matchVersion = regexWinSDK10Version.Match(sdk.GetId()); |
|
|
|
|
|
|
|
string path; |
|
|
|
|
|
|
|
if (matchVersion.Success) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Environment.SpecialFolder specialFolder = Environment.Is64BitOperatingSystem ? |
|
|
|
|
|
|
|
Environment.SpecialFolder.ProgramFilesX86 : Environment.SpecialFolder.ProgramFiles; |
|
|
|
|
|
|
|
var programFiles = Environment.GetFolderPath(specialFolder); |
|
|
|
|
|
|
|
path = Path.Combine(programFiles, "Windows Kits", "10", "include", |
|
|
|
|
|
|
|
$"10.0.{matchVersion.Groups[1].Value}.0"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
throw new Exception("Windows10SDK should not have been detected, something is terribly wrong"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var shared = Path.Combine(path, "shared"); |
|
|
|
|
|
|
|
var um = Path.Combine(path, "um"); |
|
|
|
|
|
|
|
var winrt = Path.Combine(path, "winrt"); |
|
|
|
|
|
|
|
var ucrt = Path.Combine(path, "ucrt"); |
|
|
|
|
|
|
|
Console.WriteLine(path); |
|
|
|
|
|
|
|
if (Directory.Exists(shared) && |
|
|
|
|
|
|
|
Directory.Exists(um) && |
|
|
|
|
|
|
|
Directory.Exists(winrt) && |
|
|
|
|
|
|
|
Directory.Exists(ucrt)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
includes.Add(shared); |
|
|
|
|
|
|
|
includes.Add(um); |
|
|
|
|
|
|
|
includes.Add(winrt); |
|
|
|
|
|
|
|
includes.Add(ucrt); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (win8sdks.Any()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\shared"); |
|
|
|
|
|
|
|
includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\um"); |
|
|
|
|
|
|
|
includes.Add(@"C:\Program Files (x86)\Windows Kits\8.1\include\winrt"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return includes; //We've collected all information.
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
while (fetched > 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// a COM exception means the VS 2017 COM API (therefore VS itself) is not installed, ignore
|
|
|
|
|
|
|
|
catch (COMException ex) when (ex.HResult == REGDB_E_CLASSNOTREG) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (Exception ex) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Console.Error.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return includes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Tries to get all vs 2017 instances.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="versions">Collection holding available visual studio instances</param>
|
|
|
|
|
|
|
|
/// <returns>Success of the operation</returns>
|
|
|
|
|
|
|
|
private static bool GetVs2017Instances(ICollection<ToolchainVersion> versions) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const int REGDB_E_CLASSNOTREG = unchecked((int) 0x80040154); |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var query = new SetupConfiguration(); |
|
|
|
|
|
|
|
var query2 = (ISetupConfiguration2) query; |
|
|
|
|
|
|
|
var e = query2.EnumAllInstances(); |
|
|
|
|
|
|
|
int fetched; |
|
|
|
|
|
|
|
var instances = new ISetupInstance[1]; |
|
|
|
|
|
|
|
do |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
e.Next(1, instances, out fetched); |
|
|
|
|
|
|
|
if (fetched > 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var instance = (ISetupInstance2) instances[0]; |
|
|
|
|
|
|
|
var toolchain = new ToolchainVersion |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Directory = instance.GetInstallationPath() + @"\Common7\IDE", |
|
|
|
|
|
|
|
Version = float.Parse(instance.GetInstallationVersion().Remove(2)), |
|
|
|
|
|
|
|
Value = null // Not used currently
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
versions.Add(toolchain); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
while (fetched > 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// a COM exception means the VS 2017 COM API (therefore VS itself) is not installed, ignore
|
|
|
|
|
|
|
|
catch (COMException ex) when (ex.HResult == REGDB_E_CLASSNOTREG) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (Exception ex) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Console.Error.WriteLine($"Error 0x{ex.HResult:x8}: {ex.Message}"); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|