共用方式為


桌面檔案擴充 Windows PE

Wes Miller

早在我們五年前發行 Windows PE 之前,迫不及待的客戶就已經要求我們提供更多的功能。可惜的是,Windows PE 的設計並不像 Windows XP Embedded 那樣,能夠加入更多的作業系統層,輕易地進行擴充。當然,Windows PE 必須要有基本的

Win32® 支援 (以便讓大部分的 Windows® 應用程式都能執行),以及網路和大型存放裝置支援 (以便透過網路通訊,並且能夠安裝 Windows)。但是即使從一開始,我們就想要限制殼層;藉由使用 cmd.exe 代替傳統的 Windows 檔案總管殼層,我們限制了 Windows PE 環境能夠執行的作業,更重要的是,如此一來,預設的環境就能輕易使用指令碼編寫所有自動化的工作。

所以您還是可以擴充 Windows PE,但是必須記住它是有所限制的。如果您的應用程式需要 [圖 1] 所列的任一種技術 (此清單並不完整),則可以預期應用程式將無法運作或不能正常運作。

Figure 1 缺少的 Windows API

.NET Framework (任何版本)
Active Directory® Services Interfaces (ADSI)
DirectX®
Microsoft Data Access Components (MDAC)
Jet (Access)
Visual Basic® (含 .NET 之前的版本)
需要 Windows 原始未安裝之架構的任何可執行檔類型。
Windows 檔案總管或 Internet Explorer
Windows Media® Player
SAPI、MAPI、TAPI (分別是 Windows Speech、Mail、Telephony API)

要是您不知道應用程式依存的技術,就必須查明。但是要如何知道呢?我們當初在發行之前,由於想要讓 ADO、HTML 應用程式 (HTA) 及 Windows Script Host (WSH) 元件都能在 Windows PE 下執行,所以也遇到相同的問題。不過請注意,本文雖然為您介紹追蹤這些依存性的方法,但是使用者授權合約 (EULA) 並不允許在 Windows PE 影像檔中加入 MKIMG 命令未包含的任何 Windows 二進位檔。您必須先向 Microsoft 取得授權增補合約,才能在您的環境中實作這一類變更。

認識依存性

如果您在記事本中打開某個應用程式的 .inf 檔案並仔細檢查,將可了解許多資訊。事實上,這往往是最容易理解應用程式及了解其依存性的方式。就 Windows PE 而言,重點是它極為簡化,因此您必須偵錯許多層的依存性,包括應用程式本身的直接依存性和可能產生的每一個依存性,才能讓應用程式穩定、可靠地執行。基本上,如果您不夠仔細,可能會產生一系列的依存性問題。只要無意間 (或特意) 加入幾個元件,您的影像大小和複雜性就可能大幅增加。

如果您有描述應用程式的 .inf 檔案,則可以尋找 .inf 加入您系統中的登錄機碼和檔案,得到依存性的線索。請尋找 CopyFiles 和 AddReg 區段。這些項目會指向應用程式、DLL 及您的應用程式依存的其他檔案。Windows PE 的三個增益集 (ADO、HTA 及 WSH) 當中,WSH 是最容易建立的。因為舊版的 Windows 仍然能夠使用可轉散發版本的 WSH,而且 Windows 中現在仍內建了執行 WSH 檔案關聯的 .inf (位於 %windir%\inf\wsh.inf),因此將其安裝到 Windows PE 相對而言很容易。

Orca 和快照

如果討論的應用程式是以 Microsoft® Installer (MSI) 檔案的形式散發,您有兩種方法可以找出依存性。如果您很熟悉 MSI,可以使用 Orca (編輯 Windows Installer 檔案的工具,隨附在 Windows Server® 2003 R2 Platform SDK 中散發:go.microsoft.com/fwlink/?LinkId=77941) 來檢視。您也可以安裝想要使用之元件的 MSI,以執行檔案和登錄機碼的變更分析。您可以先傾印登錄、安裝應用程式、然後再次匯出登錄,接著針對登錄執行 WinDiff (請參閱「使用 WinDiff」資訊看板)。所得結果可做為必須對登錄進行變更的範本。問題在於變更的數量可能讓人傷透腦筋。不過,您手邊若沒有 .inf 可參考 (或應用程式的作者可詢問),這可能是最佳的選項。

您可能已熟悉應用程式快照的流程。基本上,這和您要讓應用程式正常執行所進行的變更分析相同。Microsoft 以前有隨附 Windows 2000 散發執行此工作的工具,但是該工具不能在任何較新版的 Windows 中使用。許多商業應用程式 (安裝重新封裝器) 和一些免費的公用程式,都可以執行此工作。其中的一個方案會安裝包含 WinDiff 的 Platform SDK (請參閱上一段落中的連結)。請注意,若要執行 WinDiff 進行比較,最好是將應用程式安裝在 Windows Server 2003,Service Pack 1 (SP1) 上,因為這是您應該使用的 Windows PE 版本 -- 亦即根據 Standard Edition 或 Enterprise Edition (含 SP1) 建置的 Windows PE 1.6。在 Windows Server 2003 上執行此工作,其環境最接近 Windows PE 環境 (很顯然您不能在此處執行 MSI)。請遵循「使用 WinDiff」資訊看板中的步驟。

這將會告訴您許多已變更的資訊。可惜的是,沒有很容易的方法可以從登錄匯出變更的資訊,或透過擷取檔案的方式來建立參照資料,以安裝您的應用程式。您必須手動併入變更。第一版的 Windows PE 就是在這方面遇到一些最棘手的問題。要讓 HTA 元件正常工作很複雜,因為 Microsoft 中沒有這些元件的定義 (Internet Explorer® 之外)。藉由比對差異,我們才能夠加入足夠的 HTA 支援,使其能正常運作。雖然這些機碼可以手動加入 Windows PE 登錄中,但建議您在 Windows PE 啟動之後再加入機碼。您可以檢查 OC.bat 和 OC2.bat 檔案,它們是用來安裝 HTA、WSH 及 (或) ADO 支援到 Windows PE 中的檔案 (透過 Windows PE 建置工具所包含的 buildoptionalcomponents.vbs 指令碼)。

實用的工具

即使在釐清直接依存性之後,往往還是找不到您的應用程式所依存的所有二進位檔。例如,您無法知道它在執行某件工作時,是否需要另一個 DLL 或 OCX。那麼要怎樣才能知道呢?Sysinternals 著名的 Mark Russinovich (現在是 Microsoft 的技術研究員) 撰寫了一個名為 listdlls 的便利公用程式,專門執行此工作。Listdlls 可以從 microsoft.com/technet/sysinternals/utilities/ListDlls.mspx 下載。使用時請執行 listdlls.exe > dlls.txt 命令,然後檢查其輸出即可。[圖 2] 顯示 listdlls 針對自己執行的輸出。您可以將此清單和 Windows PE 所包含的 DLL 與 OCX 檔案做個比較,判斷是否有您所有應用程式的依存性 (就 listdlls 而言,已全部列出)。針對 Windows PE 中的 HTA 支援,listdlls 可以識別其他方式無法發現的依存性,這當初是一大關鍵。

圖 2 Lisdlls 針對自己執行的輸出

圖 2** Lisdlls 針對自己執行的輸出 **(按影像可放大)

但是有列出的 DLL,並不一定代表應用程式需要該 DLL 才能運作。例如,您若是載入記事本,將會看到它有載入 uxtheme.dll。Windows PE 當中並沒有此 DLL,事實上,由於沒有使用 Windows 佈景主題,因此永遠不會載入。困難的是如何判斷 listdlls 顯示的 DLL 中,哪些才是您真正需要的,哪些又是 Windows 需要時所載入的;這需要許多從錯誤中嘗試的重複過程,或是您必須非常熟悉 Windows 的低層級知識 (關於這方面的資訊,我推薦 Mark Russinovich 和 David Solomon 合著的 Microsoft Windows InternalsFourth Edition (Microsoft Press®,2004) 一書。

事實上,Mark 在免費的 Process Explorer (用來取代 Windows 工作管理員) 當中,就包含了此功能。在我看來,差別在於 listdlls 所建立的輸出較容易用於編寫指令碼以及尋找和收集遺漏的依存性。

請注意,即使您已將 DLL 加入影像中,還是需要執行一些其他的工作。也就是說,DLL 類型有兩種:需要登錄和不需要登錄的。這兩者很難分辨,只能靠嘗試登錄來區分。若要登錄 DLL (或 OCX),請執行 regsvr32 dllname.dll。如果 DLL 運作正常,就會顯示一個對話方塊,告訴您 DLL 已登錄。否則會顯示一個訊息或對話方塊,告訴您 DLL 登錄失敗,或者 DLL 無法登錄。我們在開發 Windows PE 的 HTA 和 ADO 的選擇性元件時,發現 DLL 在執行登錄時需要可寫入的儲存體,以便暫時寫入安裝用的 .inf 檔案,或記錄一些其他依存性 (例如,需要的特定目錄)。這在以前的 Windows PE 中通常會失敗。幸好這一類工作在 Windows PE 2.0 裡都能正常運作,因為預設提供了塗銷空間。

Mark 所建立並在最近發行的第三個工具名為 Process Monitor。Process Monitor 可以視為 Regmon 和 Filemon 的超集合,但提供比任一者還要多的詳細資訊,並加入了全新的處理程序通訊層。此一功能強大的工具可幫助您疑難排解 Windows 中的應用程式,並幫助您回答 DLL 真正的相互依存性問題。請按此處下載 (英文) Process Monitor。

移除 Windows PE 檔案

除了可在 Windows PE 加入新功能之外,另一個常見的要求是如何讓 Windows PE 更精簡的說明。您可以採取一些步驟,幫 Windows PE 瘦身。具有合法授權的 Windows PE 應包含建置工具的集合和一些文件。其中一份文件是名為 winpe.chm 的說明檔。如果開啟這個檔案,閱讀「Windows 預先安裝環境使用者手冊」區段,應該就可看到「縮減 Windows PE 的大小」這個主題。此區段會列出可以安全移除的一些檔案集合 (假設您不需要這些檔案)。關於可移除檔案的區段共有三個:

  • 字型檔案一律可以安全地移除。
  • 網路相關的 .inf 檔案和公用程式可以移除,但是唯有您完全不打算在網路上使用您的組建時才可這麼做。
  • 命令列公用程式不可移除。除非您明確知道檔案的功能和移除的後果,否則不建議您移除其中任何檔案。

您決定好哪些檔案可以安全地移除之後,只需編寫批次檔或其他指令檔,並在 mkimg.cmd 完成建置之後,從 Windows PE 組建移除這些檔案。

修改 Windows PE 的登錄

您可以看到我們刻意選擇在組建時不安裝選擇性的元件。雖然這代表在執行階段需要多一點的時間,但是我們就不必為如何將這些元件放回 Windows PE 來傷腦筋 -- 因為我們當時不會有時間做這些,所以很可能會造成這些元件完全被放棄。但是您若是要變更登錄 (例如當您的應用程式登錄有所變更而需要加入其中的差異),或者想要編輯用來保持應用程式正常運作的機碼時,該怎麼辨?使用 [圖 3] 中所示的 regedit 即可輕易完成。請遵循下列步驟:

  1. 執行 regedit,然後選取 HKEY_LOCAL_MACHINE Hive。
  2. 選取 [檔案] | [載入 Hive 控制檔],然後瀏覽至您的 Windows PE 組建位置。從 I386\System32\ (如果這是您放在硬碟上的影像,則是 MiniNT\System32) 底下選取 setupreg.hiv。
  3. 輸入 Hive 的暫存名稱,例如 WinPE,然後瀏覽至 HKLM 底下的該節點。
  4. 照著修改此機碼。有趣的是,請注意此節點實際上是和一般 Windows 安裝上的 HKLM\System 節點一樣。
  5. 修改完成之後,請選取在步驟 3 建立之 HKLM 底下的機碼 (這一步一定要做對,否則可能會損害您的系統)。
  6. 選取 [檔案] | [Hive 解除載入...],並於 [是] | [否] 對話方塊確認,每次都要確定您解下登錄,因為鎖定登錄會造成 Windows PE 無法建置成功。

圖 3 開啟 Windows PE 的登錄

圖 3** 開啟 Windows PE 的登錄 **(按影像可放大)

遵循這些步驟,即可修改 HKLM\System。I386\System32 底下還有另外兩個機碼可讓您修改登錄的其他部分:DEFAULT 是使用者的預設 Hive (即使您在使用 Windows PE 時是使用 SYSTEM 執行也一樣),而 SOFTWARE 則是和 HKLM\Software 相同。一如往常,修改登錄一定要小心,而且只在必要時才修改。

現在您已經有所了解,應可幫助您開始將自己喜愛的疑難排解或修復工具移到 Windows PE 上。下個月我將要討論 PSTools 套件,這也是 Mark Russinovich 所撰寫、一套非常實用的系統管理工具集合。

使用 WinDiff

WinDiff 可以幫助您找出應用程式的依存性。只要遵循下列步驟就能成功安裝及執行:

  1. 準備系統以供安裝,您應該要盡量縮短初始和最終快照之間的時間,並避免檔案或登錄的變更。
  2. 開啟命令提示字元視窗,然後執行 reg export HKLM C:\HKLM1.reg,即可完整匯出 HKEY_Local_Machine 登錄 Hive。
  3. 執行 dir C:\*.* /S > C:\C1.txt 以執行 C: 磁碟機 (假設 C: 是您的系統磁碟機) 上面所有檔案的完整傾印。
  4. 安裝您的應用程式,然後設定所有相關設定。
  5. 執行 reg export HKLM C:\HKLM2.reg。
  6. 執行 dir C:\*.* /S > C:\C2.txt。
  7. 開啟 WinDiff 並選取 [檔案 (File)] | [比較檔案... (Compare Files...)],然後從第一個 [開啟檔案 (File Open)] 對話方塊中選取 HKLM1 .reg,再從第二個對話方塊中選取 HKLM2.reg。
  8. 您應該會看到一則紅色訊息,表示何者較新。這需要一些時間,因為 HKLM 的匯出檔案可能很大,所以請耐心等候。
  9. 按兩下紅色文字以展開差異。
  10. 您可以勾選 [選項 (Options)] | [只顯示右邊的行 (Show Right-Only Lines)],設定要在比較中顯示的項目。這會讓第二個檔案中只顯示新增的行 (因此只會顯示新檔案和新登錄機碼)。

請注意,您可能需要使用 [搜尋 (Find)] 功能,才能找出與您的應用程式相關的機碼。在 [圖 A] 和 [圖 B] 中,您可以看到我所建立之虛構應用程式的檔案和登錄變更。幸好,WinDiff 提供複製和貼上的功能。若要使用這些功能,只要按一下 !> 行,再選取所要的行即可。

圖 A WinDiff 的項目

圖 A** WinDiff 的項目 **(按影像可放大)

圖 B WinDiff 中的特定機碼

圖 B** WinDiff 中的特定機碼 **(按影像可放大)

Wes Miller 任職於德州奧斯丁的 Pluck 公司 (www.pluck.com),擔任開發經理。Wes 之前任職於同樣位在奧斯丁的 Winternals Software,以及在 Microsoft 擔任 Windows 的專案經理與產品經理。Wes 的連絡方式為:technet@getwired.com

© 2008 Microsoft Corporation and CMP Media, LLC. 保留所有權利;未經允許,嚴禁部分或全部複製.