diff --git a/lib/find-visualstudio.js b/lib/find-visualstudio.js index f0710fbe9b..8c5ae96127 100644 --- a/lib/find-visualstudio.js +++ b/lib/find-visualstudio.js @@ -54,8 +54,10 @@ class VisualStudioFinder { } const checks = [ - () => this.findVisualStudio2017OrNewerUsingSetupModule(), - () => this.findVisualStudio2017OrNewer(), + () => this.findVisualStudio2019OrNewerUsingSetupModule(), + () => this.findVisualStudio2019OrNewer(), + () => this.findVisualStudio2017UsingSetupModule(), + () => this.findVisualStudio2017(), () => this.findVisualStudio2015(), () => this.findVisualStudio2013() ] @@ -114,7 +116,20 @@ class VisualStudioFinder { throw new Error('Could not find any Visual Studio installation to use') } - async findVisualStudio2017OrNewerUsingSetupModule () { + async findVisualStudio2019OrNewerUsingSetupModule () { + return this.findNewVSUsingSetupModule([2019, 2022]) + } + + async findVisualStudio2017UsingSetupModule () { + if (this.nodeSemver.major >= 22) { + this.addLog( + 'not looking for VS2017 as it is only supported up to Node.js 21') + return null + } + return this.findNewVSUsingSetupModule([2017]) + } + + async findNewVSUsingSetupModule (supportedYears) { const ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe') const vcInstallDir = this.envVcInstallDir @@ -157,12 +172,28 @@ class VisualStudioFinder { return info }) // pass for further processing - return this.processData(parsedData) + return this.processData(parsedData, supportedYears) + } + + // Invoke the PowerShell script to get information about Visual Studio 2019 + // or newer installations + async findVisualStudio2019OrNewer () { + return this.findNewVS([2019, 2022]) + } + + // Invoke the PowerShell script to get information about Visual Studio 2017 + async findVisualStudio2017 () { + if (this.nodeSemver.major >= 22) { + this.addLog( + 'not looking for VS2017 as it is only supported up to Node.js 21') + return null + } + return this.findNewVS([2017]) } // Invoke the PowerShell script to get information about Visual Studio 2017 // or newer installations - async findVisualStudio2017OrNewer () { + async findNewVS (supportedYears) { const ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe') const csFile = path.join(__dirname, 'Find-VisualStudio.cs') @@ -180,7 +211,7 @@ class VisualStudioFinder { if (parsedData === null) { return null } - return this.processData(parsedData) + return this.processData(parsedData, supportedYears) } // Parse the output of the PowerShell script, make sanity checks @@ -224,7 +255,7 @@ class VisualStudioFinder { // Process parsed data containing information about VS installations // Look for the required parts, extract and output them back - processData (vsInfo) { + processData (vsInfo, supportedYears) { vsInfo = vsInfo.map((info) => { this.log.silly(`processing installation: "${info.path}"`) info.path = path.resolve(info.path) @@ -238,11 +269,12 @@ class VisualStudioFinder { this.log.silly('vsInfo:', vsInfo) // Remove future versions or errors parsing version number + // Also remove any unsupported versions vsInfo = vsInfo.filter((info) => { - if (info.versionYear) { + if (info.versionYear && supportedYears.indexOf(info.versionYear) !== -1) { return true } - this.addLog(`unknown version "${info.version}" found at "${info.path}"`) + this.addLog(`${info.versionYear ? 'unsupported' : 'unknown'} version "${info.version}" found at "${info.path}"`) return false }) diff --git a/test/test-find-visualstudio.js b/test/test-find-visualstudio.js index ca40165a74..2c3f4e1981 100644 --- a/test/test-find-visualstudio.js +++ b/test/test-find-visualstudio.js @@ -31,12 +31,8 @@ describe('find-visualstudio', function () { it('VS2013', async function () { const finder = new TestVisualStudioFinder(semverV1, null) - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null - } - finder.findVisualStudio2017OrNewer = async () => { - return finder.parseData(new Error(), '', '') - } + finder.findNewVSUsingSetupModule = async () => null + finder.findNewVS = async () => null finder.regSearchKeys = async (keys, value, addOpts) => { for (let i = 0; i < keys.length; ++i) { const fullName = `${keys[i]}\\${value}` @@ -78,15 +74,18 @@ describe('find-visualstudio', function () { patch: 0 }, null) - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', 'VS_2017_Unusable.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2017_Unusable.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } finder.regSearchKeys = async (keys, value, addOpts) => { for (let i = 0; i < keys.length; ++i) { @@ -109,14 +108,8 @@ describe('find-visualstudio', function () { it('VS2015', async function () { const finder = new TestVisualStudioFinder(semverV1, null) - - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null - } - - finder.findVisualStudio2017OrNewer = async () => { - return finder.parseData(new Error(), '', '') - } + finder.findNewVSUsingSetupModule = async () => null + finder.findNewVS = async () => null finder.regSearchKeys = async (keys, value, addOpts) => { for (let i = 0; i < keys.length; ++i) { const fullName = `${keys[i]}\\${value}` @@ -222,15 +215,20 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) poison(finder, 'regSearchKeys') - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', + 'VS_2017_BuildTools_minimal.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2017_BuildTools_minimal.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) @@ -252,15 +250,20 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) poison(finder, 'regSearchKeys') - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', + 'VS_2017_Community_workload.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2017_Community_workload.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) @@ -282,14 +285,18 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) poison(finder, 'regSearchKeys') - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', 'VS_2017_Express.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2017_Express.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) @@ -311,15 +318,20 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) poison(finder, 'regSearchKeys') - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', + 'VS_2019_Preview.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2019_Preview.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) @@ -341,15 +353,20 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) poison(finder, 'regSearchKeys') - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', + 'VS_2019_BuildTools_minimal.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2019_BuildTools_minimal.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) @@ -371,15 +388,20 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) poison(finder, 'regSearchKeys') - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', + 'VS_2019_Community_workload.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2019_Community_workload.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) @@ -410,15 +432,20 @@ describe('find-visualstudio', function () { finder.msBuildPathExists = (path) => { return true } - finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { - return null + finder.findNewVSUsingSetupModule = async () => null + finder.findVisualStudio2019OrNewer = async () => { + const file = path.join(__dirname, 'fixtures', + 'VS_2022_Community_workload.txt') + const data = fs.readFileSync(file) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2019, 2022]) } - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const file = path.join(__dirname, 'fixtures', 'VS_2022_Community_workload.txt') const data = fs.readFileSync(file) - const vsInfo = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(vsInfo) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) } const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) @@ -440,12 +467,8 @@ describe('find-visualstudio', function () { finder.msBuildPathExists = (path) => { return true } - finder.findVisualStudio2017OrNewer = async () => { - return null - } - finder.findOldVS = async (info) => { - return null - } + finder.findNewVS = async () => null + finder.findOldVS = async () => null setupExecFixture(finder, 'VSSetup_VS_2022_workload_missing_sdk.txt') const { err, info } = await finder.findVisualStudio() assert.match(err.message, /could not find/i) @@ -489,8 +512,11 @@ describe('find-visualstudio', function () { } return false } - finder.findVisualStudio2017OrNewer = async () => { - throw new Error("findVisualStudio2017OrNewer shouldn't be called") + finder.findVisualStudio2019OrNewer = async () => { + throw new Error("findVisualStudio2019OrNewer shouldn't be called") + } + finder.findVisualStudio2017 = async () => { + throw new Error("findVisualStudio2017 shouldn't be called") } setupExecFixture(finder, fixtureName) const { err, info } = await finder.findVisualStudio() @@ -525,8 +551,7 @@ describe('find-visualstudio', function () { finder.findVisualStudio2017OrNewerUsingSetupModule = async () => { return null } - - finder.findVisualStudio2017OrNewer = async () => { + finder.findVisualStudio2017 = async () => { const data0 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', 'VS_2017_Unusable.txt'))) const data1 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', @@ -535,18 +560,22 @@ describe('find-visualstudio', function () { 'VS_2017_Community_workload.txt'))) const data3 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', 'VS_2017_Express.txt'))) - const data4 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', + const data = JSON.stringify(data0.concat(data1, data2, data3)) + const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) + return finder.processData(parsedData, [2017]) + } + finder.findVisualStudio2019OrNewer = async () => { + const data0 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', 'VS_2019_Preview.txt'))) - const data5 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', + const data1 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', 'VS_2019_BuildTools_minimal.txt'))) - const data6 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', + const data2 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', 'VS_2019_Community_workload.txt'))) - const data7 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', + const data3 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', 'VS_2022_Community_workload.txt'))) - const data = JSON.stringify(data0.concat(data1, data2, data3, data4, - data5, data6, data7)) + const data = JSON.stringify(data0.concat(data1, data2, data3)) const parsedData = finder.parseData(null, data, '', { checkIsArray: true }) - return finder.processData(parsedData) + return finder.processData(parsedData, [2019, 2022]) } finder.regSearchKeys = async (keys, value, addOpts) => { for (let i = 0; i < keys.length; ++i) {