繁体   English   中英

从在 WINE 中运行的程序执行 Shell 命令

[英]Execute Shell Commands from Program running in WINE

我有一个使用 WINE 在 Linux 上运行的 Windows 程序。

如何从 Windows 程序调用 Linux shell 命令?

使用较新的 Wine 版本(使用 Wine 1.7.38 测试) ,您可以通过以下方式在 Wine 中运行 Linux 程序(这里以启动 gedit 为例):

wineconsole cmd

...从那个葡萄酒控制台:

start /unix /usr/bin/gedit

如果您想直接从 Windows 应用程序中启动 Linux 程序,以下行对我有用:

cmd /c start /unix /usr/bin/gedit

要对此进行测试,您可以直接在 Linux 控制台上调用:

wine cmd /c start /unix /usr/bin/gedit

需要注意的一件重要事情:您要启动的程序需要设置可执行位,否则从 Wine 调用它会失败!

试试这个(在我的 Linux Mint 系统上运行 Gnome 计算器):

wineconsole cmd

...从葡萄酒控制台:

/bin/sh gcalctool

根据这个一般原则,您还可以通过编辑 wine 注册表来打开文档并将文件与 linux 应用程序关联。 在葡萄酒常见问题中有一个关于它的部分:

6.6.3 如何在 Wine 中关联本地程序和文件类型?

所以你应该能够编写 shell 脚本并调用它们。

如何从 Wine 程序调用 Linux 程序——API 方面的五点。

1. 正确的PATHEXT

在新的 Wine 版本中(至少从 2.0.1 开始),需要在PATHEXT环境变量中的可执行文件扩展名列表中添加扩展名(即只是点字符: . )。 如果没有此添加,错误消息可能会显示如下内容:

Can't recognize '/bin/bash' as an internal or external command, or batch script.

要修复注册表中的初始PATHEXT值,可以使用以下命令片段(对于每个WINEPREFIX ):

k='HKLM\System\CurrentControlSet\Control\Session Manager\Environment'
pathext_orig=$( wine reg query "$k" /v PATHEXT | tr -d '\r' | awk '/^  /{ print $3 }' )
echo "$pathext_orig" | grep -qE '(^|;)\.(;|$)' \
  || wine reg add "$k" /v PATHEXT /f /d "${pathext_orig};."

此代码检查然后修改PATHEXT如果它不包含. 仅项目。

另请参阅: 如何从 Windows 应用程序启动本机应用程序? 在 WineHQ 常见问题解答中; 注意

请注意,每次升级 Wine 时都必须进行此更改,因为只要更新 wineprefix,它就会恢复。

2. 可执行文件路径

默认情况下,您可能需要指定可执行文件的完整(或相对)路径(例如, /bin/bash ),因为 Wine 进程不会从父 Linux 进程继承PATH环境变量。 请注意,Wine 进程中的当前驱动器默认映射到 Linux 根文件夹,因此无需指定驱动器号。 /bin/bash只是有效,但不是bash

另一种方法是相应地更改 Wine 中的PATH环境变量,或更改当前目录。

当路径包含非 ASCII 字符时——作为CreateProcessA参数——路径应该在 Wine 语言环境中并根据LANG环境变量; 另请参阅Eugene在本主题中的回答,以及如何设置编码以与 Wine 中的非 Unicode 应用程序一起使用的论坛帖子。 在任何情况下,对于CreateProcessW ,路径都应该是 UTF-16。

3. 可执行格式

共享对象格式的 Linux 可执行文件不能从 Wine 执行。 请参阅: 可执行文件与共享对象以及如何在 64 位 Linux 上从 32 位 Wine 执行 shell 脚本 例如, /bin/dash可以是“ELF 64 位 LSB 共享对象”(参见file /bin/dash输出)并且在这种情况下不能从 Wine 执行。 错误信息说:

wine: Bad EXE format for Z:\bin\dash..
Can't recognize '/bin/dash' as an internal or external command, or batch script.

4.无需等待

父 Wine 进程不能在子 Linux 进程上等待(例如,通过WaitForSingleObject ),因为它没有提供子进程句柄——它只是 0。请参阅错误报告:启动 Linux 程序时 CreateProcess 没有正确设置 hProcess (状态:关闭 WONTFIX)。

然而,如果子进程使用 stdout(另见下文),父进程可以通过在特定管道上阻塞读取来间接等待子进程。

5.管道重定向的区别

也许这是 Wine 中的一个错误,但是父进程应该关闭传递给 CreateProcess 的 std 句柄,只有在关闭相应管道的自己的句柄(或就在它之前)之后。 而在 Windows 中,这些句柄可以在CreateProcess函数完成后立即关闭。 通过 MSDN,这些句柄可能会在传递后立即关闭(请参阅CreateProcess 函数):

STARTUPINFO 或 STARTUPINFOEX 中的句柄在不再需要时必须用 CloseHandle 关闭。

在 Wine 2.0.1 中,Linux 子进程中对应的管道会立即关闭,子进程会提前停止 但不是在子 Windows 进程的情况下。

尝试(其中 yourprogram 是您要在 wine 中执行的 linux/unix 程序)

ln -s /path/to/yourprogram /path/to/wineprefix/drive_c/windows/system32/yourprogram

这就是我让java工作的方式。

例如:

Z:\bin\ls

但也许您正在寻找类似http://gnuwin32.sourceforge.net/ 之类的东西,您将安装到您的葡萄酒“窗口”中? 或者已经提到的cygwin。

对我来说,我在这个网站上找到的第一个解决方案有效 - 将扩展与 winebrowser 相关联,并且当单击 wine Explorer(或其他 Windows 应用程序)中的文件时,默认的 gnome 文件查看器从 wine 启动。

以前在 wine 1.4中工作的shell scripts 解决方案不适用于 wine 1.6

但是,我注意到的问题是 Windows 编码中的名称不会转换为 Linux 区域设置,从而阻止它与例如俄语目录名称一起使用

WineHQ 常见问题解答列出的 shell 脚本可以稍作修改,例如:

#!/bin/bash
WFILE=$(echo -E $2)
FILE=$(wine winepath $WFILE)
$1 $FILE

其余的工作就像常见问题解答中描述的那样。

我喜欢Far Commander ,它确实在wine下运行,所以我设置了这两个脚本:

  1. 从 Windows 启动 Linux 应用程序

C:\\windows\\xt.bat

start /unix /usr/bin/xterm -e %*
  1. 从 wine 环境 (Far) 在 Linux 中打开文件:

C:\\windows\\xdg.bat

cd >C:\windows\command\mypwd
start /unix /etc/init.d/winopen.sh  %*

/etc/init.d/winopen.sh

#!/bin/sh
PWDF=`winepath -u 'C:\windows\command\mypwd'`
fromdos $PWDF
xdg-open $(winepath -u $(cat $PWDF)/$1)

现在我可以在 Far 命令行上输入:

xdg SomeDocument.PDF

并在 Linux 环境中得到结果。

编辑:user1182474 的评论是正确的; Wine 不会隔离它运行的程序。 (它试图隐藏它,但不是很彻底。)我完全没有使用谷歌。 下面 Psen 的评论更正确,并参考了常见问题解答。 (请注意,要使其正常工作,您可能需要通过 Wine 驱动器映射提供程序目录。或者,请参阅匿名回复者的回答。)

== 旧答案 ==

Wine 隔离它运行的程序。 如果所有应用程序都按预期运行,那么这些应用程序将呈现与 Windows 无法区分的环境。 不幸的是,这意味着您无法访问主机操作系统 (Linux) 的功能。 我的意思是,你可以修补 Wine 来做到这一点,但我的印象是它会比它的价值更多的工作。

还有希望! Cygwin 是用于 Windows 的类 Unix 环境。 您可以在 Wine 中安装 Cygwin,并使用 Cygwin 运行您的 shell 脚本。 (显然,使用 'winetricks cygwin' 安装是最简单的)像这样调用 Cygwin 的 bash shell(在一些 Wine 程序中):

c:\cygwin\bin\bash  myscript

当然,将 c:\\cygwin 更改为您安装它的任何位置。

如果您需要等待命令完成并获取其输出,请使用 SSH。 否则(如果您只需要启动它)任何这些方法都可以工作:

核心问题是 CreateProcess 返回零 PID 和 handle ,因此您不能等待子进程完成并获取它的退出代码。

我也尝试过标准管道重定向,但没有成功。 Linux 子进程的输出丢失,管道为空。

所以,和 CreateProcess 和朋友一起,你必须使用某种触发器文件,看起来不太漂亮。 就像我说的,我们将改用 SSH。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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