3

I'm using the new WLS2 on Windows 10 Home. I noticed that, when I ran "npm", the "npm" from my Windows program files was executed instead of the Linux version.

When I tried to execute cmd.exe or notepad.exe from WSL2, I noticed those also work!

How is this possible? How is WSL2 able to run Windows executables?

Additionally, how can I force WSL2 to prioritize the Linux executables over the Windows ones in cases where they have the same names?

  • 4
    Why are you shocked this works? WSL is aware of the Windows file system. So why wouldn’t it be able to run a Windows executable? The NT kernel still exists. – Ramhound Feb 14 at 19:59
  • 2
  • 3
    By specifying full paths. Windows looks into the file to decide how to run it. From CreateProcess - the ONLY way to start a program, lpApplicationName [in] Pointer to a null-terminated string that specifies the module to execute. The specified module can be a Windows-based application. It can be some other type of module (for example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer. – Mark Feb 14 at 22:19
  • Because Microsoft wanted it to. – K7AAY Feb 15 at 0:08
  • 1
    Another interesting fact is for files without a Windows' file association CMD.exe will pass it to CreateProcess to see if it knows what to do with it. So CMD (but not Explorer) will run an executable (of any supported type) no matter what it is called. – Mark Feb 15 at 4:51
4

How is WSL2 able to run Windows executables?

The Windows executable (PE binary) is added as a binfmt_misc entry in WSL2. In simple words, binfmt_misc is a Linux kernel feature which allows arbitrary executable file formats to be recognized and passed to certain programs.

In WSL2, the init binary (from which every process is forked) register the Windows PE binary as a executable and make it executable by itself (i.e. the init). Here is a output of the PE binfmt entry:

cat /proc/sys/fs/binfmt_misc/WSLInterop
enabled
interpreter /tools/init
flags: F
offset 0
magic 4d5a

WSLInterop is just a name for the entry. The magic number 4d5a is MZ which is first two bytes of Windows PE executable. Assume this is a fingerprint with which init (the interpreter) recognizes PE binary.

Users can disable the registry with this command:

echo 0 | sudo tee /proc/sys/fs/binfmt_misc/WSLInterop

Further readings:

| improve this answer | |
6

It will run any executable (Windows or linux) that is in your $PATH environment variable. It searches the directories in order, so if you want to run the linux versions by preference, make sure those directories are before the windows directories in the path

| improve this answer | |
  • why is WSL able to run windows executables? – Daniel Santos Feb 14 at 19:49
  • 4
    Because ultimately your still running Windows. While WSL 2 is running a Linux kernel it’s aware of Windows. – Ramhound Feb 14 at 20:00
3

bash is running as a pico process. When you try to run a program, the linux subsystem driver recognizes the request to run a process and calls ZwCreateUserProcess in the windows kernel, creating the windows process.

It can call the function because all system calls made by pico processes are translated into NT calls in kernel mode, both via LXCORE.SYS and the kernel, ntoskrnl.exe.

| improve this answer | |
  • 1
    That’s no longer the case with WSL2 though, which is essentially a VM. – Daniel B Feb 18 at 7:12
1

Create an alias for the Linux apps you wish to prioritize over their Windows namesakes. For example:

alias foo='/path/to/bar'

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.