Skip to content

Commit

Permalink
fix: detect VS2017 even on highly restricted environments
Browse files Browse the repository at this point in the history
  • Loading branch information
refack committed Feb 10, 2017
1 parent 5c1a60a commit e267594
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules/
npm-debug.log
out/
coverage/
tools/*.exe
78 changes: 69 additions & 9 deletions lib/gyp/platform/win.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const gyp = require('../../gyp');
const fs = gyp.bindings.fs;
const path = gyp.bindings.path;
const process = gyp.bindings.process;
const execSync = gyp.bindings.execSync;

const win = exports;

Expand Down Expand Up @@ -391,25 +392,84 @@ win.getOSBits = function getOSBits() {
return 32;
};

function tryVS7(hostBits, target_arch) {
function tryVS7_powershell() {
try {
const psFile = path.join(__dirname,
'..', '..', '..', 'tools', 'Get-VSConfig.ps1');
const vsSetupRaw = gyp.bindings.execSync(`powershell ${psFile}`).toString();
const cs = path.join(__dirname, '..', '..', '..', 'tools', 'VSConfig.cs');
const cmd = `powershell -Command \
"&{ Add-Type -Path ${cs} ; [VisualStudioSetup]::Main()}"`;
const vsSetupRaw = execSync(cmd).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 vsSetup.InstallationPath;
} catch (e) {
gyp.bindings.log('Couldn\'t find VS7 with powershell' , e.message);
}
}

function tryVS7_CSC() {
const VREG = /.*v(\d+\.\d+).*/;
const dirCMD = 'dir /b /s %windir%\\Microsoft.NET\\Framework\\csc.exe';
try {
const files = execSync(dirCMD)
.toString()
.trim()
.split(/[\r|\n]+/g)
.map(f => [Number(f.replace(VREG, '$1')), f]);
const maxVer = Math.max.apply(Math, files.map(v => v[0]));
const cscPath = files.find(v => v[0] === maxVer)[1];
const toolsPath = path.join(__dirname, '..', '..', '..', 'tools');
const csPath = path.join(toolsPath, 'VSConfig.cs');
const exePath = path.join(toolsPath, 'VSConfig.exe');
execSync(`${cscPath} /out:${exePath} ${csPath}`);
const vsSetupRaw = execSync(exePath).toString();
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;
}, {});
const VsDevCmd = path.join(vsSetup.InstallationPath,
'Common7', 'Tools', 'VsDevCmd.bat');
const argArch = target_arch === 'x64' ? 'amd64' : 'x86';
const argHost = hostBits === 64 ? 'amd64' : 'x86';
return `${VsDevCmd} -arch=${argArch} -host_arch=${argHost} -no_logo`;
return vsSetup.InstallationPath;
} catch (e) {
gyp.bindings.log('Couldn\'t find VS7 with a compiled exe', e.message);
}
}

function tryVS7_registry() {
const magicKey = String.raw`HKLM\Software\Microsoft\VisualStudio\SxS\VS7`;
const magicQuery = `reg query ${magicKey} /reg:32`;
const qRet = execSync(magicQuery).toString().trim();
if (qRet.includes('ERROR')) {
gyp.bindings.log('Couldn\'t find VS7 in registry:(');
return;
}
const values = qRet.split(/[\r|\n]+/g).slice(1);
const ret = values.map(v => {
const parts = v.trim().replace(/\s+/g, ' ').split(' ');
return [Number(parts[0]), parts[2]];
});
if (!ret.length) {
gyp.bindings.log('Couldn\'t find VS7 in registry');
return;
}
const maxVer = Math.max.apply(Math, ret.map(v => v[0]));
return ret.find(v => v[0] === maxVer)[1];
}

win._forTesting = {tryVS7_powershell, tryVS7_CSC, tryVS7_registry};

function tryVS7(hostBits, target_arch) {
const btPath = tryVS7_powershell() || tryVS7_CSC() || tryVS7_registry();
if (!btPath) {
gyp.bindings.log('Couldn\'t find VS7 :(');
return;
}
const VsDevCmd = path.join(btPath, 'Common7', 'Tools', 'VsDevCmd.bat');
const argArch = target_arch === 'x64' ? 'amd64' : 'x86';
const argHost = hostBits === 64 ? 'amd64' : 'x86';
return `${VsDevCmd} -arch=${argArch} -host_arch=${argHost} -no_logo`;
}

function findOldVcVarsFile(hostBits, target_arch) {
Expand Down
17 changes: 17 additions & 0 deletions test/platform-win-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,23 @@ describe('gyp.platform.win', () => {
if (process.platform === 'win32') {
describe('genEnvironment', function () {
this.timeout(20000);

it('try with powershell', () => {
const path = win._forTesting.tryVS7_powershell();
assert(path.includes('BuildTools'));
});

it('try with csc', () => {
const path = win._forTesting.tryVS7_CSC();
assert(path.includes('BuildTools'));
});

it('try with registry', () => {
const path = win._forTesting.tryVS7_registry();
assert(path.includes('BuildTools'));

});

it('resolve for x64', () => {
const env = win.resolveDevEnvironment('x64');
assert(env, 'didn\'t get ENVIRONMENT :(');
Expand Down
4 changes: 0 additions & 4 deletions tools/Get-VSConfig.ps1 → tools/VSConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
$Source = @"
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -171,6 +170,3 @@ private static void PrintInstance(ISetupInstance2 setupInstance2)
Console.WriteLine();
}
}
"@
Add-Type -TypeDefinition $Source -Language CSharp
[VisualStudioSetup]::Main()

0 comments on commit e267594

Please sign in to comment.