扫一扫
关注微信公众号

在Linux上如何运行Windows应用程序(2)
2006-08-30   easywine

更多 Wine 所不能做的

看完 Wine 的可用性问题后,现在让我们来总结在尝试使用 Wine 时一些常见的技术问题。

缺少 DLL,这可能是最常见的问题:很多安装由于缺少 DLL 而失败。人们应该熟练使用调试器来决定下一步如何去做。(稍后将深入讨论调试器)。

DLL 版本问题

一些安装程序在开始之前会检查现有的系统 DLL。Wine 解决这一问题的方法是,创建假 DLL 以满足安装程序的需要。不过,有一些安装程序会更进一步并深入检查 DLL 以获得它们的版本。这对假的 DLL 来说要求太高了,会导致安装失败。

DLL 加载次序

Wine 有对很多 Windows DLL 的实现,而且如果可用,它还可以使用原始的 Windows DLL。如果两种 DLL 都可用,好像显然应该选择总是使用 Windows 自己的 DLL,但实际上 Windows DLL 有时会包含不能被满足的依赖。要确定是更应该使用 Wine 的 DLL 还是应该使用本机 DLL,惟一的方法是,基于各个应用程序反复进行试验。

DLL 中的函数

当一个 Wine DLL 没有实现 Windows 中相应的 DLL 的全部功能时,应用程序可能会遭遇函数调用失败。由于 DLL 是动态加载的,可能没有办法事先知道会发生这样的事情。这是一个复杂的问题,有一些可做的工作,但最终实际来说它只是取决于应用程序的代码如何编写。

有一些因素会减轻这些问题。一方面,您将会一个一个地遇到这些问题,而不是一次遇到全部问题,这样处理起来要容易些。另外,您遇到的那些问题可能其他人曾遇到过并已经解决(而且解决方案已经公布出来)。Wine 用户组非常活跃,会提供许多帮助,每周一次的 Wine 时事通讯(参阅 参考资料)是极好的信息资源。

Wine 中还没有实现的 Win32 API

在 Wine 中,很多 Win32 API5 的函数是残缺不全的。最常见的原因是,相当多的 Win32 API 并没有被文档化。这就意味着一个特别的应用程序可能会调用某个函数,而完全没有关于此函数的可用资料。例如,我们在运行一个简单的 RPC 程序时发现了 RtlAnsiCharToUnicodeChar 这个函数。在 MSDN 上的搜索结果显示没有关于这个函数的资料,而且没有关于所有 RtlXXXX 类别函数的资料。因此,如果它们在 Wine 中的实现对一些应用程序来说至关重要,那么人们可能只有去猜测它们的行为了。

商用的 Wine

CodeWeavers 为 Wine 做了很多工作。多年来他们为 Wine 项目贡献了很多代码,他们出售商用版本的 Wine,其改进的用户界面解决了我们在本文中提出的很多问题。

例如,CodeWeavers 的二进制安装文件会在用户的开始菜单中添加一个 Crossover 条目;安装后,绝大多数 Crossover 相关的任务可以通过开始菜单条目来完成。在开放源代码的 Wine 中,所有这些任务 -- 安装、程序执行以及其他任务 -- 都必须在命令行中执行。此外,CodeWeavers Crossover 将会尝试去为新安装的软件包配置一个合理的默认值,如果需要的话会在安装完成后自动重新引导,并以其他形式减轻用户的负担。

CodeWeavers 使用开放源代码的 Wine 作为他们的 Crossover 产品的基础,所以,除非遇到上面我们讨论过的可用性问题,否则,在其中一个产品中能运行的应用程序,在另一个产品中同样也能运行。要深入了解 CodeWeavers 和 Crossover,以及要获得可以在 Wine 上运行的应用程序列表,请参阅在 参考资料中列出的链接。

应用程序安装分析

由于 Wine 支持 Windows 可执行文件的运行,您会想当然地认为可以使用程序的安装程序从头安装,这是正常的。不幸的是,几乎不会那样。对 Windows 安装过程的理解将有助于解释原因。下面非常简单地描述了 Windows 安装程序通常要做的事情的(不必是这个次序):

将文件拷贝到一些目录。

注册 DLL,并将其他应用程序相关的信息添加到注册表中。

在安装过程中,有时会检查 DLL 的版本(如前面所提到的)。

修改 INI 和一些其他配置文件。

因而,Wine 会遇到两种类型的问题,必须按顺序解决:

安装过程中的问题。

执行过程中的问题。

在调试 Wine 安装的过程中,如果您同时有一个可用的 Windows 系统的话会非常有帮助。那样,您可以对 Windows 安装使用追踪器以确切断定哪些文件被拷贝,哪些注册表条目被添加或更新,哪个 INI 文件被修改,等等。记录安装步骤的顺序并与失败的 Wine 安装相比较,是故障诊断的好向导。

在 Linux 上安装 Wine

如果您正在使用 Red Hat 或者 SUSE,最简单的方法是从 CD 安装 Wine。不过,如果那些 CD 比较老,您可能需要通过源文件安装,因为 Wine 项目经常更新。如果通过源文件安装,您会发现 Wine 用户指南(参阅 参考资料以获得链接)是一份价值无法估量的资料。简化的安装过程如下:

解开源文件后,切换到 tools 目录下以用户身份运行 ./tools/wineinstall。

在 tools 目录下运行 winecheck 脚本来检查安装。您可能不会获得 100% 的成功,但只要没有关键问题就行。

Wine 的所有配置都保存在 ~/.wine/config 文件中。这个文件很容易理解:它描述了您希望将 Linux 文件系统的哪部分看作是 Windows C 驱动器,以及 DLL 的加载次序等其他的细节。

您应该可以快速进行了。例如,要安装 WinZip 8.1,您可以下载安装程序并在命令行中运行 wine winzip81.exe 。

快速浏览一下可以了解很多内容:您可以看到 WinZip 在运行,它的文件浏览器组件显示出熟悉的 Windows 驱动器 C、软盘驱动器 A、一个 CD-ROM M 以及另外的 Z 驱动器。您可以猜到,所有这些都映射在我们上面提到的 ~/.wine/config 文件中。下面是文件中与 所示驱动器有关的片断:

清单 1. Wine 的配置文件

CODE:[Copy to clipboard][Drive A]
"Path" = "/mnt/floppy"
"Type" = "floppy"
"Label" = "FLOPPY1"
"Device" = "auto"
[Drive C]
"Path" = "/home/aditya/aug14/3/c"
"Type" = "hd"
"Label" = "fake_windows"
"Filesystem" = "win2k"
"Codepage" = "0"
[Drive Z]
"Path"="/home/aditya/downloads/wine/"
"Type" = "hd"
"Label" = "wine src"
"Filesystem" = "win95"
[Drive M]
"Path" = "/mnt/cdrom"
"Type" = "cdrom"
"Label" = "CD-ROM1"
"Filesystem" = "win95"
"Device" = "auto"

从这里您可以看到, M 驱动器实际上是 /mnt/cdrom;C 驱动器是 /home/aditya/aug14/3/c;等等。

Windows 应用程序移植到 Linux 的一个例子

技术上讲,使 Windows 可执行文件在 Wine 中运行并不是移植,但是经常被认为是移植。这也是测试一个应用程序是否适合使用 Winelib 进行移植的好办法。要获得关于使用 Wine Winelib 库编译来移植源代码的资料,请参阅 参考资料中关于 Winelib 用户指南的链接。

我们已经整理了一个非常简单的应用程序,来说明 Windows 程序如何在 Wine 中运行。程序创建了一个窗口;从一个 DLL 中加载了两个函数,有一些对话框。我们将继续使用非常简单的例子;作为实际应用中的例子,我们非常鼓励您用 MS Office 等大型应用程序进行同样的尝试。

同时,这个例子可以通过让您体验代码的运行来入门。

运行代码

示例 DLL 的源代码在 DLLCode 目录中,使用 DLL 的源代码在 callDll 目录中。要运行只需要将两者(DLL 文件和可执行文件)存放于同一目录下,并运行 callDll.exe 。winetests 文件夹中的 README.TXT 文件描述了如何在 Linux 上 Wine 中执行那个二进制程序。

如果您愿意,可以随意打开项目文件并进行修改。

DLLCode 项目正确编译后,您可以在 Debug 文件夹中看到 DLLSample.dll 文件。这个文件是 callDll 项目所需要的。为了您的方便,DLLSample.dll 已经存放于 callDll 中正确的位置。举例说明的 callDll 中产生的可执行文件的依赖;您可以使用 Dependency Walker 来查看其他程序的依赖(参阅 参考资料)。

比较

下面是对运行于 Windows XP 上的和运行于 Red Hat 的 GNOME 中的消息框(Message Box)视觉上的对比:

对应于此的 C 代码(callDll.cpp 中第 60 行):

MessageBox(NULL, "Wine test ending...", "", MB_OK);

这提出了一些有趣的观察:

最明显的观察之一是,双方都支持消息框的使用;这是将 Windows 调用有可能映射为 Linux 中相应部分的因素之一。如果您在 Wine 源代码中搜索 MessageBox,您可以找到说明文件,文件中详细说明了哪些函数已经被实现,哪些被去除掉。

大小、字体、颜色和标题栏以及其他可视元素继承自底层操作系统设置的默认值。

从本文中所包括的追踪文件中,您可以看到这个函数是在 user32.dll 中实现的。如果您在文件中搜索字符串“Wine test ending”,您将更深入地理解到,当您在做一些与在消息框中显示字符串同样简单的事情时,幕后发生了多少事情。

既然我们已经看过了一个 Win32 函数,让我们来看一下,当 simpleDLL.dll 中实现的我们自己的函数之一被调用时,幕后发生了什么。我们将展示追踪记录中的片断来说明何时 simpleDll.dll 被加载,哪些函数被导出,在哪一点 getTitle() 函数被调用(按 README 文件中的步骤生成完全的追踪记录):

清单 2. 解析出我们的 DLL 的路径并检查 DLL 是否存在

CODE:
[Copy to clipboard]0009:trace:module:MODULE_GetLoadOrder looking for
C:\documents\article-sample\simpleDLL.dll

清单 3. 这一行展示我们的 DLL 所导出的函数

CODE:
[Copy to clipboard]Module name is simpleDLL.dll, 3 functions, 3 names
Ord RVA Addr Name
1 0000100a 0x1000100a add
2 0000100f 0x1000100f getSize
3 00001014 0x10001014 getTitle

清单 4. 这里展示了 getTitle 被调用的位置

CODE:
[Copy to clipboard]0009:CALL simpleDLL.getTitle((0x40580000,00000002,00000040):
returning 405b7210
) ret=004010d4
0009:RET simpleDLL.getTitle() retval=1002901c ret=004010d4

分析一个更大的应用程序或多或少与此相似,不过您当然会得到多得多的细节,会遇到没有被实现的函数,等等。故障诊断通常大概是提供缺少的 DLL 和调整配置;偶尔,您将需要去实现或修复一个函数。

结束语

如果您正在寻找将现有的 Windows 应用程序转移到 Linux 的方法,开放源代码的 Wine 和来自 CodeWeavers 的商用产品都是极好的选择。应用程序可以运行于 Wine 之上,或者使用 Winelib 工具包进行移植。

Wine 还为那些希望介入开放源代码软件的人们提供了一个独一无二的机会。从特别困难的到适合初学者的,有大量的各种复杂程度的项目--而且 Wine 社区非常活跃并提供非常多的支持。

参考资料

下载本文中演示的 示例应用程序。

自 Wine 下载页获得 Wine 的二进制文件和源代码,通过 Wine 的官方 Web 站点 WineHQ 深入了解 Wine 及其历史。

Wine 用户指南将帮您起步。 Chapter 7. Troubleshooting / Reporting bugs 中包括很多指向有用信息资料的链接,比如 Frank's Corner for tips and tricks;可以到 Wine Google Group 寻求帮助,到 dll-files.com 寻找缺少的 DLL —— 还有更多。

依赖浏览器和追踪工具将有力地帮助您让 Windows 二进制程序平滑到运行于 Wine 之上。Microsoft Platform SDK 中包括depends.exe Dependency Walker;在 Sysinternals 可以找到类似的工具;同时 Epsilon Squared提供了一个非常好的 Windows 安装追踪工具。

DLL 不只会在 Wine 中引发问题;对 Windows 用户来说它们也是著名的问题源头。MSDN 文章 The End of DLL Hell解释了原因。

Windows API 文档的缺乏是美国政府对 Microsoft 的反拖拉斯诉讼的内容。自由软件基金会(Free Software Foundation)首席法律顾问 Eben Moglen 在 Free Software Matters: Shaking Up The Microsoft Settlement中讨论了 API 和解决条款。

除了 Wine 用户指南以外, WineHQ 文档页上还列出了其他很多有用的文章。

在 WineHQ 查找现在的和以前的 Wine Weekly News的话题。

Winelib 用户指南涵盖了使用 Winelib 将您的应用程序移植到 Linux 和 Unix 所需要知道的所有内容。

Wine 应用程序数据库列出了那些可以通过 Wine 运行于 Linux 上的 Windows 应用程序,并有很多它们的截图。

Francois Gouget有很多 关于 Wine 的资料,包括如何做出贡献;为什么 Wine 重要;有趣的 Wine API 统计以及更多资料!

CodeWeavers 的 Crossover 产品基于 Wine。

WineX 也是构建于 Wine 源代码之上。WineX 的目标是为 DirectX 实现一个 Linux 兼容层,因此其名字中包含字母 X。

Wine 不是一个仿真器 —— 但是有很多可用的仿真器可以让您在 Linux 或 Unix 上运行 Windows 二进制程序。其中包括 VMWare 和 Win4Lin,这两个都是私有的;还有开放源代码的 Bochs 项目。使用这些程序,Windows 的一个拷贝可以运行于仿真器之上,这个仿真器会确保 Windows OS 所需要的硬件条件都得到满足。

用于交叉生成应用程序的 Xmingwin( developerWorks, 2003 年)让您只需要重新编译就可以将 Linux 应用程序移植到 Windows。

WebSphere Homepage Builder for Linux需要 Keio 大学定制的 Wine 版本。

在 developerWorks Linux 专区可以找到更多为 Linux 开发者准备的参考资料。

在 Developer Bookstore 的 Linux 区可以找到大量 关于 Linux 的书籍。

热词搜索:

上一篇:在Linux上如何运行Windows应用程序(1)
下一篇:Linux下Apache、php3、MySQL整合方法

分享到: 收藏