fnm icon indicating copy to clipboard operation
fnm copied to clipboard

exec doesn't work for executables other than "node" on Windows

Open jakebailey opened this issue 1 year ago • 1 comments

When using fnm exec, only node works; npm and npx don't execute and so I get my global install (or, no install if fnm is my main way of getting Node).

Here's a PowerShell script which shows what I'm referring to:

if (!(Test-Path -Path fnm-windows)) {
    Invoke-WebRequest -URI "https://github.com/Schniz/fnm/releases/download/v1.35.1/fnm-windows.zip" -OutFile "fnm-windows.zip"
    Expand-Archive -Path "fnm-windows.zip" -DestinationPath "fnm-windows"
}

$env:FNM_DIR="$PWD/fnm-windows"

echo "fnm install 8"
./fnm-windows/fnm install 8

echo "node --version"
node --version

echo "npm --version"
npm --version

echo "fnm exec --using=8 -- node --version"
./fnm-windows/fnm exec --using=8 -- node --version

echo "fnm exec --using=8 -- npm --version"
./fnm-windows/fnm exec --using=8 -- npm --version

echo 'fnm exec --using=8 -- node -e "console.log(process.env.PATH)"'
./fnm-windows/fnm exec --using=8 -- node -e "console.log(process.env.PATH)"

The output is:

fnm install 8
Installing Node v8.17.0 (x64)
warning: Version already installed at "C:\\Users\\jabaile\\testing/fnm-windows\\node-versions\\v8.17.0"
node --version
v20.8.0
npm --version
10.1.0
fnm exec --using=8 -- node --version
v8.17.0
fnm exec --using=8 -- npm --version
10.1.0
fnm exec --using=8 -- node -e "console.log(process.env.PATH)"
C:\Users\jabaile\testing/fnm-windows\node-versions\v8.17.0\installation;C:\Program Files\PowerShell\7;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Microsoft SQL Server\150\Tools\Binn\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Users\jabaile\scoop\apps\python\current\Scripts;C:\Users\jabaile\scoop\apps\python\current;C:\Users\jabaile\go\bin;C:\Users\jabaile\scoop\apps\rustup\current\.cargo\bin;C:\Users\jabaile\scoop\apps\volta\current\appdata\bin;C:\Users\jabaile\scoop\apps\gcc\current\bin;C:\Users\jabaile\scoop\shims;C:\Users\jabaile\AppData\Local\Microsoft\WindowsApps;C:\Users\jabaile\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\jabaile\AppData\Local\Microsoft\WindowsApps;C:\Users\jabaile\AppData\Local\Programs\Microsoft VS Code Insiders\bin

I suspect that something in the chain isn't handling Window's PATHEXT or something. I'm not super familiar with rust's process handling, but this seems relevant: https://doc.rust-lang.org/std/process/struct.Command.html#platform-specific-behavior

Note on Windows: For executable files with the .exe extension, it can be omitted when specifying the program for this Command. However, if the file has a different extension, a filename including the extension needs to be provided, otherwise the file won’t be found.

So, this is roughly https://github.com/rust-lang/rust/issues/37519 and using https://docs.rs/which/latest/which/ on the command before running would probably fix this. That or, always using a shell on Windows. Not sure what Node itself does here. I know Go handles this for you (https://cs.opensource.google/go/go/+/master:src/os/exec/lp_windows.go), but Rust seems to not want to do this and remain a syscall wrapper.

jakebailey avatar Oct 13 '23 17:10 jakebailey

Note that this probably also affects any other commands run via fnm exec, since fnm is running them directly.

jakebailey avatar Oct 13 '23 17:10 jakebailey