Skip to content

Instantly share code, notes, and snippets.

@noseratio
Last active May 2, 2023 11:31
Show Gist options
  • Save noseratio/d81888eda77620e526c7eb2c3b75cba8 to your computer and use it in GitHub Desktop.
Save noseratio/d81888eda77620e526c7eb2c3b75cba8 to your computer and use it in GitHub Desktop.
A workaround for "node-gyp is unable to find msbuild if VS2019 is installed": https://github.com/nodejs/node-gyp/issues/1663
<#
This is a workaround for "node-gyp is unable to find msbuild if VS2019 is installed"
https://github.com/nodejs/node-gyp/issues/1663
It create a shim EXE as "MSBuild\15.0\Bin\MSBuild.exe" to target "MSBuild\Current\Bin\MSBuild.exe"
By noseratio - MIT license - use at your own risk!
It requires admin mode, I use wsudo/wsudox (https://chocolatey.org/packages/wsudo) for that:
wsudo powershell -f make-msbuild-shim.ps1
#>
#Requires -RunAsAdministrator
#Requires -Version 5.1
$ErrorActionPreference = "Stop"
$vsBasePath = . "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" `
-latest `
-requires Microsoft.Component.MSBuild `
-property installationPath -format value
if (!$vsBasePath) {
throw "VS2017+ must be installed"
}
$msbuildSimPath = [System.IO.Path]::Combine($vsBasePath, "MSBuild\15.0\Bin\MSBuild.exe")
if ([System.IO.File]::Exists($msbuildSimPath)) {
Write-Host "Already exists: $msbuildSimPath"
exit 0;
}
# Create the shim .EXE using C#
$code = @"
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
static class MSBuildShim
{
static void Main()
{
var thisExe = Process.GetCurrentProcess().MainModule.FileName;
var thisExeDir = Path.GetDirectoryName(thisExe);
var newExe = Path.GetFullPath(Path.Combine(thisExeDir, "..\\..\\Current\\Bin", "MSBuild.exe"));
if (!File.Exists(newExe))
throw new FileNotFoundException(newExe);
var process = new Process();
process.StartInfo.FileName = newExe;
process.StartInfo.Arguments = String.Join("\u0020", Environment.GetCommandLineArgs().Skip(1));
process.StartInfo.UseShellExecute = false;
if (!process.Start())
throw new InvalidOperationException(newExe);
process.WaitForExit();
Environment.ExitCode = process.ExitCode;
}
}
"@
Add-Type -TypeDefinition $code `
-OutputType ConsoleApplication `
-OutputAssembly "$msbuildSimPath" `
-ReferencedAssemblies "System.Core.dll"
Write-Host "Shim created at: $msbuildSimPath"
@k1epto
Copy link

k1epto commented Jun 10, 2019

doesn't run for me, errors

@noseratio
Copy link
Author

doesn't run for me, errors

@bipolarmorgan: That's not enough of diagnostics info for fixing anything, but make sure you use PowerShell (not PowerShell Core!) and run the script as admin.

@spiraljacobs
Copy link

spiraljacobs commented Jun 26, 2019

I've tried this script. Ran it, and then ran it again to make sure it ran properly :
PS C:\> .\make-msbuild-shim.ps1 Already exists: C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\15.0\Bin\MSBuild.exe

Running npm install (which triggers a node-gyp build of node-sass), I still get node-gyp trying to spawn build tools at the wrong location - 15.0\Bin\MSBuild.exe rather than MSBuild\Current\Bin:

gyp ERR! UNCAUGHT EXCEPTION gyp ERR! stack Error: spawn C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\15.0\Bin\MSBuild.exe ENOENT gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:264:19) gyp ERR! stack at onErrorNT (internal/child_process.js:456:16) gyp ERR! stack at processTicksAndRejections (internal/process/task_queues.js:84:9) gyp ERR! System Windows_NT 10.0.17763

@noseratio
Copy link
Author

@spiraljacobs, it still runs as C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\15.0\Bin\MSBuild.exe, as far as node-gyp is concerned. This file is just a shim generated by my powershell script, and it invokes MSBuild\Current\Bin\MSBuild.exe as a child process.
It's hard to tell why it is not working on your system as expected, but you should not be using it anyway, rather use node-gyp 5.0 that comes with VS2019 support.

@spiraljacobs
Copy link

Ah, when I was installing node-gyp@latest, didn't seem to be pulling anything that supported 2019.
Anyway, thanks for the help!

@k1epto
Copy link

k1epto commented Jun 26, 2019

doesn't run for me, errors

@bipolarmorgan: That's not enough of diagnostics info for fixing anything, but make sure you use PowerShell (not PowerShell Core!) and run the script as admin.

True it's not, but you also didn't ask for any information, you assumed your script works... when it doesn't.

Cannot process the "#requires" statement at line 10 because it is not in the correct format.
The "#requires" statement must be in one of the following formats:
 "#requires -shellid <shellID>"
 "#requires -version <major.minor>"
 "#requires -pssnapin <psSnapInName> [-version <major.minor>]"
At line:1 char:30
+ c:\temp\make-msbuild-shim.ps1 <<<<
    + CategoryInfo          : ObjectNotFound: (:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

@noseratio
Copy link
Author

noseratio commented Jun 26, 2019

Cannot process the "#requires" statement at line 10 because it is not in the correct format.

@bipolarmorgan, on the machine where you're getting this error, can you go to the admin command prompt and run powershell get-host

What is the output?

@k1epto
Copy link

k1epto commented Jun 26, 2019

C:\Users\User>powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\User> get-host


Name             : ConsoleHost
Version          : 2.0
InstanceId       : 92b8f577-b391-4aa6-aae5-8cb6beb4cf45
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

@noseratio
Copy link
Author

noseratio commented Jun 26, 2019

Name : ConsoleHost
Version : 2.0

@bipolarmorgan, so this is Windows 7 with PowerShell 2.0 and that's why you're seeing this error. You need PowerShell 5.1, as you could tell from #Requires -Version 5.1. You can get it here: https://chocolatey.org/packages/powershell.
Better yet, use the new node-gyp 5.0 and never mind this gist, it was meant to be a workaround until node-gyp properly supports VS2019.
That said, I'm not sure VS2019 is even supported on Windows 7, as the latter reaches its End of Life phase on January 14, 2020.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment