我如何从 WSL (Ubuntu) 运行 Windows 可执行文件 Bash

How can I run a Windows executable from WSL (Ubuntu) Bash

随着 2016 年夏季的 Windows 10 周年更新,运行 ubuntuWindows Subsystem for Linux (WSL) 中的二进制文件,一个 "lightweight" 虚拟化子系统。

不幸的是,启动 C:\Windows\System32\bash.exe,另一个 bash ELF 二进制文件在 WSL 内部启动了一个进程,您无法从中逃脱!您只能启动其他 ELF 二进制文件。

那么如何从 Windows Bash 执行 *.exe 文件?[1]

[1] Microsoft's "official" GH support repo.

中也提出了问题

原生解决方案

官方解决方案提供了 Windows 10 Insider Preview Update (14951) is based on the almost forgotten binfmt_msc Linux 启动二进制文件的功能。 binfmt_misc 的注册命令是这样的(其中 /init 是临时 binfmt_misc "interpreter" 对于 win-executables):

sudo echo ":WSLInterop:M::MZ::/init:" > /proc/sys/fs/binfmt_misc/register

然后 win-executable 将像常规程序一样启动:

$ export PATH=$PATH:/mnt/c/Windows/System32
$ notepad.exe
$ ipconfig.exe | grep IPv4 | cut -d: -f2
$ ls -la | findstr.exe foo.txt
$ cmd.exe /c dir

Not that any win-executable must reside in the windows (DrvFs) file-system - not on the Linux's file-system (VolFs) - in order to inherit a proper Windows working-directory.

cbwin替代方案

在您获得最新版本之前,项目 cbwin 提供了一种解决方法,方法是在 WSL 中安装 3 个新的 linux 命令:

  • wcmd:通过cmd.exe调用win-executable。
  • wrun:用CreateProcess同步调用win-executable,等死(不使用cmd.exe)。
  • wstart:启动分离(异步)命令(使用 cmd.exe)。

要使用它们,您必须:

  1. 安装 cbwin
    • 一个新的 outbash.exe 将安装在您的常规 Windows 文件系统中(在您的 %PATH% 中的某处),加上
    • WSL 文件系统中的 3 个 linux-命令。
  2. 使用此 outbash.exe(无论您安装在何处)启动 WSL,而不是 C:\Windows\System32\bash.exe
  3. 在任何 win 可执行文件前加上这些命令之一,例如wrun notepad.

提示: 如果使用 wcmdwrun 启动的可执行文件生成了任何子项,则这些子项仅在可执行文件保持活动状态时存在。

换句话说,尝试用wcmd启动notepad.exe是行不通的,因为notepad会在启动后被杀死——在这种情况下使用 wrun(同步)或 wstart(异步)。

Windows 10 Creators Update(内部版本 1703,2017 年 4 月)中,这是原生支持的。所以你现在可以 运行 Windows 来自 Linux...

的二进制文件

notepad.exe 或任何其他 .exe(需要扩展名 needs being on your path,一些旧版本需要整个路径)

...反之亦然,使用以下其中一项:

  • bash.exe -c command_to_run 即:bash.exe -c ls
  • bash -c command_to_run 即:bash -c ls
  • wsl command_to_run 即:wsl "ls";或指定要使用的发行版 运行 使用:
    • ubuntu run ls

有关详细信息,请参阅上面的链接文章。

虽然命令行中的 运行 和 .exe 有效,但当 运行 从 PHP 通过 exec() 时,我无法让它工作.但是,添加 /init 确实有效。这是我在 Windows:

上安装的 GraphicsMagick 的工作 /usr/local/bin/convert 文件
#!/bin/sh
/init "$(ls /mnt/c/Program*/GraphicsMagick*/gm.exe|tail -1)" convert "$@"

我对此有点困惑。我添加了一个符号链接:

$ ls -l /c                                                                                               
lrwxrwxrwx 1 root root 5 Dec  3 10:24 /c -> mnt/c  

现在 ls /c 给出与 ls /mnt/c

相同的结果

但是现在: /c/Program\Files/Java/jdk1.8.0_211/bin/java.exe -version ==> 没有

但是:

/mnt/c/Program\ Files/Java/jdk1.8.0_211/bin/java.exe  -version 
java version "1.8.0_211"                                                                                                Java(TM) SE Runtime Environment (build 1.8.0_211-b12)                                                                   Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode) 

其他 windows 可执行文件也会发生同样的事情。 WSL 有实现符号链接的错误吗?

为什么不直接使用

$ powershell.exe Start filename

Start 是 Windows 相当于大多数 linux 上的 xdg-open 或 macOS 上的 open,这意味着“使用默认桌面应用程序打开”。我喜欢给它起个别名来打开。