简体   繁体   中英

Interact with apps installed on Windows using WSL2

I got my WSL2 up and running. On Windows level I installed node.js and now I want to run npm install snowflake-sdk from Ubuntu level. Terminal returns -bash: /mnt/c/Program Files/nodejs/npm: /bin/sh^M: bad interpreter: No such file or directory while PowerShell works fine.

Question is: is it possible to interact with Windows level installed applications using WSL2's terminal?

Note:


harzvor's helpful answer provides good background information.

It is possible to make calling npm from a Windows-installed Node.js copy from WSL2 work, though it's not obvious and a bit cumbersome - though you could wrap the workaround in a custom function or script :

# From WSL2; note the required use of '.exe'
node.exe 'c:/Program Files/nodejs/node_modules/npm/bin/npm-cli.js' install snowflake-sdk

The above, which relies on Node.js being installed in its default location on Windows, calls npm indirectly , using essentially the same technique that the CLI entry point on Windows , the npm.cmd batch file , uses.

Note:

  • In order to target a Windows executable from WSL, you must include the filename extension explicitly , such as node.exe rather than node .

  • Without it, eg with npm , the Linux subsystem looks for an extension-less file by that name in the $PATH folders, which does not work.

    • Such a file actually does exist even on Windows, but it is a shebang-based script designed for Unix -like platforms, and basically just dead weight in a Windows installation; the Linux subsystem still tries to execute it, but fails, because it uses CRLF ( \\r\\n ) newlines rather than the expected LF-only ( \\n ) newlines. As a result, the unexpected CR that follows #!/bin/sh (represented as ^M in the error message) is considered a part of the executable path , so the invocation fails. [1]

    • Even fixing that problem manually (converting to LF-only newlines) doesn't help, however, because of how the shell script constructs the full path to the npm-cli.js entry point : it expresses it as an UNC path that tries to target the Windows file-system location via the WSL file-system - eg,
      \\\\wsl$\\Ubuntu-20.04\\mnt\\c\\... - which is explicitly disallowed . [2]

  • Calling the batch file, npm.cmd , explicitly, doesn't work either - neither directly nor with cmd.exe /c npm.cmd ... :

    • Direct invocation of a *.cmd file fails obscurely - not sure if that's a bug as of Windows 10 20H2.
    • Via cmd.exe /c it fails too, because cmd.exe doesn't support UNC paths as the current directory and the WSL2-internal current directory path is invariably expressed as one (eg, \\\\wsl$\\Ubuntu-20.04\\home\\jdoe\\project\\some-project ).
      cmd.exe defaults to the Windows directory in this case, so installation of packages to the current WSL directory('s project) won't work).
  • Providing the full Windows-native path to the npm CLI's main .js file to node.exe , as shown above, works as expected , since Node.js seems to otherwise be handling UNC paths that refer to WSL2 file-system directories and files, such as the calling WSL2's shell current directory, properly.


[1] On Ubuntu 20.04, the CR in the shebang line itself no longer seems to be a problem, but the CRs in the remaining lines still are, so the invocation still fails, even more obscurely, which error messages such as : not foundram Files/nodejs/npm: 3: .

[2] The reason is that the Linux dirname utility is used to determine the shell script's own directory in order to determine npm-cli.js 's full path, and this utility by design operates from the perspective of the Linux file-system, which ends up expressing the script's Windows file-system location in this indirect, unsupported manner.

> is it possible to interact with Windows level installed applications using WSL2's terminal?

Yes, you can run notepad.exe from WSL and it will open Notepad in Windows.

More documentation: https://docs.microsoft.com/en-us/windows/wsl/interop#run-windows-tools-from-linux

Solving the NPM issue

If I try running npm -v in WSL, I get an error about it not being able to find a file:

PS C:\Users\harvey> bash
harvey@harvey-w10x64-defiance:/mnt/c/Users/harvey$ npm -v
internal/modules/cjs/loader.js:968
  throw err;
  ^

Error: Cannot find module 'C:\mnt\c\Program Files\nodejs\node_modules\npm\bin\npm-cli.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:965:15)
    at Function.Module._load (internal/modules/cjs/loader.js:841:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

The path to the file is mostly correct but it has appended C:\\mnt to it.

I managed to get around this by running npm by giving Node the path to the npm-cli.js file.

You can run:

node.exe \c\Program Files\nodejs\node_modules\npm\bin\npm-cli.js -v

But that runs into the same error.

I then tried this:

PS C:\Users\harvey> bash
harvey@harvey-w10x64-defiance:/mnt/c/Users/harvey$ cd "/mnt/c/Program Files/nodejs/node_modules/npm/bin"
harvey@harvey-w10x64-defiance:/mnt/c/Program Files/nodejs/node_modules/npm/bin$ ../../../node.exe npm-cli.js -v
6.14.6

From here I was finally able to get some output from the NPM CLI.

From here I can install the package but it will likely be installed in the wrong location.

I couldn't seem to get npm working from anywhere in the filesystem. This may be a limitation with NPM. Perhaps if you try messing with your path env vars, you can get it to work?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM