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

Posted

技术标签:

【中文标题】如何从 WSL (Ubuntu) Bash 运行 Windows 可执行文件【英文标题】:How can I run a Windows executable from WSL (Ubuntu) Bash 【发布时间】:2016-12-19 15:07:09 【问题描述】:

随着 2016 年夏季的 Windows 10 周年更新,可以在“轻量级”虚拟化子系统 Windows Subsystem for Linux (WSL) 中运行 ubuntu 二进制文件。 p>

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

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

[1] 在Microsoft's "official" GH support repo 中也提出了问题。

【问题讨论】:

另请参阅 Bash on Windows - alias for exe files 以了解避免在 shell 脚本中添加显式 .exe 扩展的要求。 【参考方案1】:

本机解决方案

Windows 10 Insider Preview Update (14951) 提供的官方解决方案基于几乎被遗忘的binfmt_msc Linux 工具,用于启动二进制文件。 binfmt_misc 的注册命令如下所示(其中/init 是 win 可执行文件的临时 binfmt_misc“解释器”):

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

并不是说任何 win 可执行文件都必须驻留在 windows (DrvFs) 文件系统中 - 而不是在 Linux 的文件系统 (VolFs) 中 - 以便继承一个合适的 Windows 工作目录。

cbwin 替代方案

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

wcmd:通过cmd.exe 调用win 可执行文件。 wrun:与​​CreateProcess同步调用一个win可执行文件,等待死亡(不使用cmd.exe)。 wstart:启动分离(异步)命令(使用cmd.exe)。

要使用它们,您必须:

    安装cbwin: 一个新的 outbash.exe 将安装在您的常规 Windows 文件系统中(在您的 %PATH% 中的某个位置),另外 WSL 文件系统中的 3 个 linux 命令。 使用outbash.exe(无论您安装在哪里)来启动 WSL,而不是 C:\Windows\System32\bash.exe! 使用这些命令之一为任何 win 可执行文件添加前缀,例如wrun notepad.

提示:如果使用wcmdwrun 启动的可执行文件生成了任何子代,则这些子代仅在该可执行文件仍然存在时才能存活。

换句话说,尝试用wcmd 启动notepad.exe 是行不通的,因为记事本 将在启动后立即被杀死 -- 使用wrun(同步)或@在这种情况下为 987654344@(异步)。

【讨论】:

哎哟!这是一种解决方法,但有时这就是我们所拥有的(赞成!)。感谢分享。 使用 Creators Update (15063),运行命令行和 GUI exe 都可以正常运行。 我必须使用echo ":WSLInterop:M::MZ::/init:" |sudo tee /proc/sys/fs/binfmt_misc/register,否则它会说Permission denied【参考方案2】:

在 Windows 10 Creators Update(内部版本 1703,2017 年 4 月)中,这是本机支持的。因此,您现在可以从 Linux 运行 Windows 二进制文件...

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

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

【讨论】:

可能值得指出的是,他们将命令从 bash 更改为 wsl,但看起来 bash 仍然有效,但可能已被弃用。 请注意:您必须在 exe 中包含扩展名和大小写正确的名称才能正常工作。 我无法让它正常工作。例如,我安装了 firefox (firefox.exe),但在 bash 提示符下键入 firefox.exe 会导致 firefox.exe: command not found 哦我明白了:需要运行/mnt/c/Program Files/Mozilla\ Firefox/firefox.exe @xotonic 从 WSL bash 调用 windows exe - 您需要包含扩展名,即 nodepad.exe【参考方案3】:

从命令行运行.exe 时,当通过exec()php 运行时,我无法让它工作。但是,添加 /init 确实有效。这是我在 Windows 上安装的 GraphicsMagick 的工作 /usr/local/bin/convert 文件:

#!/bin/sh
/init "$(ls /mnt/c/Program*/GraphicsMagick*/gm.exe|tail -1)" convert "$@"

【讨论】:

【参考方案4】:

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

$ 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 是否有实现符号链接的错误?

【讨论】:

我也试过这个 - 直接创建了一个指向 .exe 的符号链接,仍然没有运气。 针对特定 .exe 的另一种解决方法(有点烦人)创建一个代理 bash 脚本 - /mnt/d/path/to/executable.exe "$@" 这对我来说已经足够了,我只是想访问 anaconda 的 Windows 安装。 截至今天,2020 年 11 月 9 日,/c/Program\ Files/Java/jdk1.8.0_211/bin/java.exe -version 为我提供了具有 /mnt 的确切输出。【参考方案5】:

为什么不直接使用

$ powershell.exe Start filename

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

【讨论】:

注意cmd.exe /c start是一样的。

以上是关于如何从 WSL (Ubuntu) Bash 运行 Windows 可执行文件的主要内容,如果未能解决你的问题,请参考以下文章

我的 WSL 终端失去了颜色

从 WSL 运行某些东西的 Windows bash 脚本

WSL Ubuntu 挂起,如何重启?

text WSL Ubuntu .bash_aliases

当 Docker 桌面在 WSL2 中运行时,bash 中的长工作目录

如何从 WSL 连接到本地 Windows SQL Server 实例?