更多 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 用戶組非?;钴S,會提供許多幫助,每周一次的 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 的配置文件
|
從這里您可以看到, 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 是否存在
|
清單 3. 這一行展示我們的 DLL 所導出的函數
|
清單 4. 這里展示了 getTitle 被調用的位置
|
分析一個更大的應用程序或多或少與此相似,不過您當然會得到多得多的細節,會遇到沒有被實現的函數,等等。故障診斷通常大概是提供缺少的 DLL 和調整配置;偶爾,您將需要去實現或修復一個函數。
結束語
如果您正在尋找將現有的 Windows 應用程序轉移到 Linux 的方法,開放源代碼的 Wine 和來自 CodeWeavers 的商用產品都是極好的選擇。應用程序可以運行于 Wine 之上,或者使用 Winelib 工具包進行移植。
Wine 還為那些希望介入開放源代碼軟件的人們提供了一個獨一無二的機會。從特別困難的到適合初學者的,有大量的各種復雜程度的項目--而且 Wine 社區非?;钴S并提供非常多的支持。
參考資料
下載本文中演示的 示例應用程序。
自 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 的書籍。