-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use minimal
powershell
script to extract VS2017 location and versio…
…n via COM* Work with all flavors of VS2017, even the minimal "C++ Build Tools" *https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/
- Loading branch information
Showing
2 changed files
with
206 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,52 @@ | ||
module.exports = { | ||
locateMsbuild: locateMsbuild, | ||
locateVS2017: locateVS2017, | ||
getVS2017WinSDKVersion: getVS2017WinSDKVersion, | ||
setGypVS2017Env: setGypVS2017Env | ||
} | ||
|
||
var log = require('npmlog') | ||
, fs = require('fs') | ||
, path = require('path') | ||
, cp = require('child_process') | ||
, win = process.platform == 'win32' | ||
, msgFormat = require('util').format | ||
, findPython = require('./find-python') | ||
|
||
var vs2017_install_path | ||
, vs2017_win_sdk_ver | ||
|
||
function run_locate(gyp, callback) { | ||
if (!win) { | ||
return callback(null, '', '') | ||
} | ||
|
||
if (vs2017_install_path || vs2017_install_path === '') { | ||
return callback(null, vs2017_install_path, vs2017_win_sdk_ver) | ||
} | ||
|
||
var python = gyp.opts.python || process.env.PYTHON || 'python2' | ||
, findvc_path = path.join(__dirname, '..', 'find_vs2017.py') | ||
|
||
findPython(python, locate_vc); | ||
|
||
function locate_vc(err, python_bin) { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
log.verbose('find vs2017', 'obtaining vs2017 install path using script %s', | ||
findvc_path) | ||
cp.execFile(python_bin, [findvc_path], function(err, stdout, stderr) { | ||
if (err) { | ||
return callback(err) | ||
} | ||
if (stdout) { | ||
vs2017_install_path = stdout.split('\r\n')[0] | ||
log.verbose('find vs2017', 'found Visual Studio 2017 in %s', vs2017_install_path) | ||
get_sdk_version(python_bin) | ||
} else { | ||
log.verbose('find vs2017', | ||
'no valid Visual Studio 2017 installation found') | ||
vs2017_install_path = '' | ||
vs2017_win_sdk_ver = '' | ||
} | ||
}) | ||
} | ||
|
||
function get_sdk_version(python_bin) { | ||
log.verbose('find vs2017', 'obtaining installed Windows SDKs') | ||
cp.execFile(python_bin, [findvc_path, vs2017_install_path], | ||
function(err, stdout, stderr) { | ||
if (err) { | ||
return callback(err) | ||
} | ||
if (stdout) { | ||
vs2017_win_sdk_ver = stdout.split('\r\n')[0] | ||
log.verbose('find vs2017', 'found VS2017 WinSDK %s', vs2017_win_sdk_ver) | ||
} else { | ||
log.verbose('find vs2017', 'no installed sdks found') | ||
} | ||
|
||
callback(null, vs2017_install_path, vs2017_win_sdk_ver) | ||
}) | ||
var vs2017Setup | ||
|
||
function tryVS7 (gyp) { | ||
if (vs2017Setup) return vs2017Setup; | ||
try { | ||
const psFile = path.join(__dirname, '..', 'tools', 'Get-VSConfig.ps1'); | ||
const vsSetupRaw = cp.execSync('powershell ' + psFile).toString(); | ||
if (!vsSetupRaw) return; | ||
const vsSetup = vsSetupRaw.split(/[\r|\n]/g).reduce((s, l) => { | ||
const lParts = l.split(': '); | ||
if (lParts.length > 1) s[lParts[0]] = lParts[1]; | ||
return s; | ||
}, {}); | ||
return vs2017Setup = vsSetup; | ||
} catch (e) { | ||
gyp.log.verbose('try VS7', 'Couldn\'t find VS2017 :('); | ||
} | ||
|
||
} | ||
|
||
|
||
function locateMsbuild(gyp, callback) { | ||
run_locate(gyp, function(err, vs_path, sdk) { | ||
if (err) { | ||
return callback(err) | ||
} | ||
if (vs_path === '') { | ||
return callback() | ||
} | ||
var msbuild_location = path.join(vs_path, 'MSBuild', | ||
'15.0', 'Bin', 'MSBuild.exe') | ||
log.verbose('find vs2017', 'looking for msbuild in %s', msbuild_location) | ||
fs.access(msbuild_location, function(err) { | ||
callback(null, err ? null : msbuild_location) | ||
}) | ||
}) | ||
} | ||
var vsSetup = tryVS7(gyp) | ||
if (!vsSetup)return callback() | ||
|
||
function locateVS2017(gyp, callback) { | ||
run_locate(gyp, function(err, vs_path, sdk) { | ||
if (err) { | ||
callback(err) | ||
} else { | ||
callback(null, vs_path === '' ? null : vs_path) | ||
} | ||
var msbuild_location = path.join(vsSetup.InstallationPath, 'MSBuild', | ||
'15.0', 'Bin', 'MSBuild.exe') | ||
log.verbose('find vs2017', 'looking for msbuild in %s', msbuild_location) | ||
fs.access(msbuild_location, function(err) { | ||
callback(null, err ? null : msbuild_location) | ||
}) | ||
} | ||
|
||
function getVS2017WinSDKVersion(gyp, callback) { | ||
run_locate(gyp, function(err, vs_path, sdk) { | ||
if (err) { | ||
callback(err) | ||
} else { | ||
callback(null, sdk === '' ? null : sdk) | ||
} | ||
}) | ||
} | ||
|
||
function setGypVS2017Env(gyp, callback) { | ||
locateVS2017(gyp, setPath) | ||
|
||
function setPath(err, vs_path) { | ||
if (err) { | ||
return callback(err) | ||
} | ||
if (vs_path) { | ||
process.env['vs2017_install'] = vs_path | ||
getVS2017WinSDKVersion(gyp, setSDK) | ||
} else { | ||
callback() | ||
} | ||
} | ||
var vsSetup = tryVS7(gyp); | ||
if (!vsSetup)return callback() | ||
|
||
function setSDK(err, sdk) { | ||
if (err) { | ||
return callback(err) | ||
} | ||
if (sdk) { | ||
process.env['vs2017_sdk'] = sdk | ||
} | ||
callback() | ||
} | ||
gyp.opts.msvs_version = '2017'; | ||
process.env['vs2017_install'] = vsSetup.InstallationPath; | ||
process.env['vs2017_sdk'] = vsSetup.SDK.replace(/\d+$/, '0') | ||
callback(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
$Source = @" | ||
using System; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using Microsoft.VisualStudio.Setup.Configuration; | ||
namespace Microsoft.VisualStudio.Setup.Configuration | ||
{ | ||
[CompilerGenerated] | ||
[Flags] | ||
[TypeIdentifier("310100ba-5f84-4103-abe0-e8132ae862d9", "Microsoft.VisualStudio.Setup.Configuration.InstanceState")] | ||
[ComVisible(true)] | ||
public enum InstanceState : uint | ||
{ | ||
None = 0, | ||
Local = 1, | ||
Registered = 2, | ||
NoRebootRequired = 4, | ||
NoErrors = 8, | ||
Complete = 4294967295 | ||
} | ||
[CompilerGenerated] | ||
[Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[TypeIdentifier] | ||
[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); | ||
} | ||
[CompilerGenerated] | ||
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[TypeIdentifier] | ||
[ComImport] | ||
public interface ISetupConfiguration | ||
{ | ||
} | ||
[CompilerGenerated] | ||
[Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[TypeIdentifier] | ||
[ComImport] | ||
public interface ISetupConfiguration2 : ISetupConfiguration | ||
{ | ||
[SpecialName] | ||
[MethodImpl(MethodCodeType = MethodCodeType.Runtime)] | ||
void _VtblGap1_3(); | ||
[return: MarshalAs(UnmanagedType.Interface)] | ||
IEnumSetupInstances EnumAllInstances(); | ||
} | ||
[CompilerGenerated] | ||
[Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[TypeIdentifier] | ||
[ComImport] | ||
public interface ISetupInstance | ||
{ | ||
[SpecialName] | ||
[MethodImpl(MethodCodeType = MethodCodeType.Runtime)] | ||
void _VtblGap1_4(); | ||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetInstallationVersion(); | ||
} | ||
[CompilerGenerated] | ||
[Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[TypeIdentifier] | ||
[ComImport] | ||
public interface ISetupInstance2 : ISetupInstance | ||
{ | ||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetInstanceId(); | ||
[SpecialName] | ||
[MethodImpl(MethodCodeType = MethodCodeType.Runtime)] | ||
void _VtblGap1_2(); | ||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetInstallationPath(); | ||
[SpecialName] | ||
[MethodImpl(MethodCodeType = MethodCodeType.Runtime)] | ||
void _VtblGap2_4(); | ||
[return: MarshalAs(UnmanagedType.U4)] | ||
InstanceState GetState(); | ||
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] | ||
ISetupPackageReference[] GetPackages(); | ||
ISetupPackageReference GetProduct(); | ||
} | ||
[CompilerGenerated] | ||
[Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] | ||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | ||
[TypeIdentifier] | ||
[ComImport] | ||
public interface ISetupPackageReference | ||
{ | ||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetId(); | ||
[SpecialName] | ||
[MethodImpl(MethodCodeType = MethodCodeType.Runtime)] | ||
void _VtblGap1_4(); | ||
[return: MarshalAs(UnmanagedType.BStr)] | ||
string GetType(); | ||
} | ||
} | ||
public static class VisualStudioSetup | ||
{ | ||
public static int Main() | ||
{ | ||
try | ||
{ | ||
var query = | ||
(ISetupConfiguration2) | ||
Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D"))); | ||
var enumSetupInstances = query.EnumAllInstances(); | ||
var rgelt = new ISetupInstance2[1]; | ||
int pceltFetched; | ||
do | ||
{ | ||
// ISSUE: reference to a compiler-generated method | ||
enumSetupInstances.Next(1, rgelt, out pceltFetched); | ||
if (pceltFetched > 0) | ||
PrintInstance(rgelt[0]); | ||
} while (pceltFetched > 0); | ||
return 0; | ||
} | ||
catch (Exception ex) | ||
{ | ||
Console.Error.WriteLine("Error 0x{0:x8}: {1}", ex.HResult, ex.Message); | ||
return ex.HResult; | ||
} | ||
} | ||
private static void PrintInstance(ISetupInstance2 setupInstance2) | ||
{ | ||
Console.WriteLine("InstallationPath: {0}", setupInstance2.GetInstallationPath()); | ||
Console.WriteLine("Product: {0}", setupInstance2.GetProduct().GetId()); | ||
foreach (var package in setupInstance2.GetPackages()) | ||
{ | ||
if (package.GetType() != "Exe") continue;; | ||
var id = package.GetId(); | ||
if (id.IndexOf("SDK", StringComparison.Ordinal) == -1) continue; | ||
var parts = id.Split('_'); | ||
if (parts.Length < 2) continue; | ||
var sdkVer = parts[1]; | ||
char[] chars = { '1', '0', '8' }; | ||
if (sdkVer.IndexOfAny(chars) == -1) continue; | ||
Console.WriteLine("SDK: {0}", sdkVer); | ||
} | ||
Console.WriteLine(); | ||
} | ||
} | ||
"@ | ||
Add-Type -TypeDefinition $Source -Language CSharp | ||
[VisualStudioSetup]::Main() |