使用套件支援架構入門

套件支援架構是開放原始碼套件,可協助您將修正程式套用至現有的桌面應用程式 (而不需要修改程式碼) ,使其可以在 MSIX 容器中執行。 套件支援架構有助於讓應用程式遵循最新執行階段環境的最佳做法。

本文提供深入等不同,瞭解套件支援架構的每個元件,以及使用它的逐步指南。

瞭解套件支援架構中的內容

封裝支援架構包含可執行檔、運行時間管理員 DLL,以及一組執行時間修正。

套件支援架構

程式如下:

  1. 建立設定檔,以指定您想要套用至應用程式的修正程式。
  2. 修改套件以指向封裝支援架構 (.PSF) 啟動器可執行檔。

當使用者啟動應用程式時,套件支援架構啟動器是第一個執行的可執行檔。 該啓動器會讀取組態檔,並將執行階段修正程式和執行階段管理員 DLL 插入至應用程式處理程序。 當應用程式有需要時,執行階段管理員就會套用修正程式,以在 MSIX 容器內執行應用程式。

封裝支援架構 DLL 插入

步驟1:識別已封裝的應用程式相容性問題

首先,為您的應用程式建立套件。 然後,安裝它、執行它,然後觀察其行為。 您可能會收到可協助您找出相容性問題的錯誤訊息。 您也可以使用處理程序監視器來找出問題。 常見的問題與有關工作目錄和程式路徑許可權的應用程式假設有關。

使用進程監視器找出問題

進程監視器 是一個功能強大的公用程式,可觀察應用程式的檔案和登錄作業及其結果。 這可協助您瞭解應用程式相容性問題。 開啟進程監視器之後,新增篩選 (篩選 > 篩選 ... ) 只包含來自應用程式可執行檔的事件。

ProcMon 應用程式篩選

事件清單隨即出現。 針對其中許多事件,[結果] 資料行中會出現「成功」這個字。

ProcMon 事件

(選擇性)您可以篩選事件,只顯示失敗。

ProcMon 排除成功

如果您懷疑檔案系統存取失敗,請搜尋位於 System32/SysWOW64 或封裝檔案路徑底下的失敗事件。 篩選也在這裡也有説明。 從這份清單的底部開始向上滾動。 最近出現在這份清單底部的失敗。 請注意包含像是「拒絕存取」和「找不到路徑/名稱」等字串的錯誤,並忽略看起來不會可疑的內容。 PSFSample有兩個問題。 您可以在清單中看到出現在下列影像中的問題。

ProcMon Config.txt

在此映射中出現的第一個問題中,應用程式無法從位於 "C:\ Windows \SysWOW64" 路徑的 "Config.txt" 檔案讀取。 應用程式不太可能會嘗試直接參考該路徑。 最可能的情況是,它會嘗試使用相對路徑從該檔案讀取,且根據預設,「System32/SysWOW64」是應用程式的工作目錄。 這表示應用程式預期其目前的工作目錄會設定為封裝中的某個位置。 在 appx 內查看,我們可以看到檔案存在於與可執行檔相同的目錄中。

應用程式 Config.txt

下圖顯示第二個問題。

ProcMon 記錄檔

在此問題中,應用程式無法將 .log 檔寫入其封裝路徑。 這會建議檔案重新導向修復可能有所説明。

步驟2:尋找執行時間修正

.PSF 包含您現在可以使用的執行時間修正,例如檔案重新導向修復。

檔案重新導向修復

您可以使用檔案重新導向 修復 ,重新導向無法從在 MSIX 容器中執行的應用程式存取的目錄中寫入或讀取資料的嘗試。

例如,如果您的應用程式寫入到與您應用程式可執行檔位於相同目錄中的記錄檔,則您可以使用檔案重新導向 修復 ,在其他位置(例如本機應用程式資料存放區)中建立該記錄檔。

來自社區的執行時間修正

請務必查看GitHub頁面的「社區投稿」。 其他開發人員可能已解決類似您的問題,並已共用執行時間修正。

步驟3:套用執行時間修正

您可以使用 Windows SDK 中的一些簡單工具來套用現有的執行時間修正,並遵循下列步驟。

  • 建立封裝版面配置資料夾
  • 取得套件支援架構檔案
  • 將它們新增至您的套件
  • 修改套件資訊清單
  • 建立設定檔

讓我們逐一完成每項工作。

建立封裝版面配置資料夾

如果您已經有 msix (或 .appx) 檔案,您可以將其內容解壓縮至版面配置資料夾,以作為封裝的臨時區域。 您可以使用 MakeAppx 工具,從命令提示字元使用工具,以 SDK 的安裝路徑為基礎,您可以在 Windows 10 電腦上找到 PC 上的 makeappx.exe 工具: x86: C:\Program Files (x86) \ Windows Kits\10\bin\x86\makeappx.exe x64: C:\Program Files (x86) \ Windows Kits\10\bin\x64\makeappx.exe

makeappx unpack /p PSFSamplePackage_1.0.60.0_AnyCPU_Debug.msix /d PackageContents

這會提供您如下所示的內容。

封裝版面配置

如果您沒有 msix (或 .appx) 檔案開始使用,您可以從頭開始建立封裝資料夾和檔案。

取得套件支援架構檔案

您可以使用獨立的 Nuget 命令列工具或 Visual Studio 來取得 .PSF Nuget 套件。

使用命令列工具取得封裝

從這個位置安裝 Nuget 命令列工具: https://www.nuget.org/downloads 。 然後,從 Nuget 命令列執行下列命令:

nuget install Microsoft.PackageSupportFramework

或者,您也可以重新命名套件延伸模組,以 .zip 並解壓縮。 您需要的所有檔案都會在 [/bin] 資料夾底下。

使用 Visual Studio 取得封裝

在 Visual Studio 中,以滑鼠右鍵按一下您的方案或專案節點,然後選擇其中一個 [管理 Nuget 封裝] 命令。 搜尋 PackageSupportFramework.psf ,以在 Nuget.org 上尋找套件。然後,安裝它。

將套件支援架構檔案新增至您的套件

將必要的32位和64位 .PSF Dll 和可執行檔新增至套件目錄。 使用下表做為指引。 您也會想要包含任何您需要的執行時間修正。 在我們的範例中,我們需要檔案重新導向執行時間修正。

應用程式可執行檔是 x64 應用程式可執行檔是 x86
PSFLauncher64.exe PSFLauncher32.exe
PSFRuntime64.dll PSFRuntime32.dll
PSFRunDll64.exe PSFRunDll32.exe

您的套件內容現在看起來應該像這樣。

封裝二進位檔

修改套件資訊清單

在文字編輯器中開啟您的套件資訊清單,然後將 Executable 元素的屬性設定 Application 為 .psf Launcher 可執行檔的名稱。 如果您知道目標應用程式的架構,請選取適當的版本,PSFLauncher32.exe 或 PSFLauncher64.exe。 如果沒有,PSFLauncher32.exe 將可在所有情況下運作。 以下為範例。

<Package ...>
  ...
  <Applications>
    <Application Id="PSFSample"
                 Executable="PSFLauncher32.exe"
                 EntryPoint="Windows.FullTrustApplication">
      ...
    </Application>
  </Applications>
</Package>

建立設定檔

建立檔案名 config.json ,並將該檔案儲存到套件的根資料夾。 修改已宣告的 config.xml 檔案應用程式識別碼,以指向您剛剛取代的可執行檔。 使用您從「進程監視器」取得的知識,您也可以設定工作目錄,也可以使用檔案重新導向修復來將讀取/寫入重新導向至封裝相關的 "PSFSampleApp" 目錄下的 .log 檔案。

{
    "applications": [
        {
            "id": "PSFSample",
            "executable": "PSFSampleApp/PSFSample.exe",
            "workingDirectory": "PSFSampleApp/"
        }
    ],
    "processes": [
        {
            "executable": "PSFSample",
            "fixups": [
                {
                    "dll": "FileRedirectionFixup.dll",
                    "config": {
                        "redirectedPaths": {
                            "packageRelative": [
                                {
                                    "base": "PSFSampleApp/",
                                    "patterns": [
                                        ".*\\.log"
                                    ]
                                }
                            ]
                        }
                    }
                }
            ]
        }
    ]
}

以下是設定 json 架構的指南:

Array 索引鍵
應用程式所需 id IdApplication 封裝資訊清單中使用元素的屬性值。
應用程式所需 可執行檔 您要啟動之可執行檔的封裝相對路徑。 在大部分的情況下,您可以在修改之前從套件資訊清單檔中取得此值。 這是元素的屬性值 ExecutableApplication
應用程式所需 workingDirectory (選擇性) 封裝相對路徑,用來做為啟動應用程式的工作目錄。 如果您未設定此值,作業系統會使用該 System32 目錄作為應用程式的工作目錄。
處理程序 可執行檔 在大部分的情況下,這會是上述設定的名稱, executable 並移除路徑和副檔名。
修復 dll 要載入之修復 msix/.appx 的封裝相對路徑。
修復 config (選擇性) 控制修復 dll 的運作方式。 此值的確切格式會因修復修復而異,因為每個修復可以視需要解讀此「blob」。

applicationsprocesses 和索引 fixups 鍵是陣列。 這表示您可以使用 config.xml 檔案指定一個以上的應用程式、進程和修復 DLL。

封裝和測試應用程式

接著,建立套件。

makeappx pack /d PackageContents /p PSFSamplePackageFixup.msix

然後加以簽署。

signtool sign /a /v /fd sha256 /f ExportedSigningCertificate.pfx PSFSamplePackageFixup.msix

如需詳細資訊,請參閱如何建立套件簽署憑證,以及如何使用 signtool 簽署封裝

使用 PowerShell 安裝套件。

注意

請記得先卸載套件。

powershell Add-AppPackage .\PSFSamplePackageFixup.msix

執行應用程式,並觀察套用執行時間修正的行為。 視需要重複診斷和封裝步驟。

檢查封裝支援架構是否正在執行

您可以檢查執行時間修正是否正在執行。 若要這樣做,請開啟 工作管理員 然後按一下 [ 更多詳細資料]。 尋找已套用封裝支援架構的應用程式,並展開應用程式詳細資料,以檢視更多詳細資料。 您應該能夠看到封裝支援架構正在執行。

使用追蹤修復

診斷已封裝應用程式相容性問題的替代方法是使用追蹤修復。 此 DLL 包含在 .PSF 中,並提供應用程式行為的詳細診斷視圖,類似于進程監視器。 它是特別設計來顯示應用程式相容性問題。 若要使用追蹤修復,請將 DLL 加入至封裝,將下列片段新增至您的 config.xml,然後封裝和安裝您的應用程式。

{
    "dll": "TraceFixup.dll",
    "config": {
        "traceLevels": {
            "filesystem": "allFailures"
        }
    }
}

根據預設,追蹤修復會篩選掉可能被視為「預期」的失敗。 例如,應用程式可能會嘗試無條件地刪除檔案,而不檢查是否已存在,而忽略結果。 這可能會導致某些非預期的失敗被篩選掉,因此在上述範例中,我們選擇接收檔案系統函數的所有失敗。 這樣做的原因是,我們知道從 Config.txt 檔案讀取的嘗試會失敗,並出現「找不到檔案」訊息。 這是經常被觀察到的失敗,而且通常不會被視為非預期的。 在實務上,最好是只從未預期的失敗開始篩選,然後在發生仍無法識別的問題時,返回所有失敗。

根據預設,追蹤修復的輸出會傳送至附加的偵錯工具。 在此範例中,我們不會附加偵錯工具,而會改為使用 SysInternals 的 DebugView 程式來查看其輸出。 執行應用程式之後,我們可以看到與之前相同的失敗,這會將我們指向相同的執行時間修正。

找不到 TraceShim 檔案

拒絕 TraceShim 存取

偵錯工具、擴充或建立執行時間修正

您可以使用 Visual Studio 來偵測執行時間修正、擴充執行時間修正,或從頭建立一個。 您必須進行這些動作才能成功。

  • 新增封裝專案
  • 加入執行時間修正的專案
  • 新增啟動 .psf Launcher 可執行檔的專案
  • 設定封裝專案

當您完成時,您的解決方案看起來會像這樣。

完成的解決方案

讓我們看看此範例中的每個專案。

Project 目的
DesktopApplicationPackage 此專案是以Windows 應用程式封裝專案為基礎,而且會輸出 MSIX 封裝。
Runtimefix 這是 c + + Dynamic-Linked 程式庫專案,其中包含一或多個做為執行時間修正的取代函數。
PSFLauncher 這是 c + + 空的 Project。 此專案是收集套件支援架構之執行時間可散發檔案的位置。 它會輸出可執行檔。 該可執行檔是當您啟動方案時執行的第一件事。
WinFormsDesktopApplication 此專案包含桌面應用程式的原始程式碼。

若要查看包含所有這些專案類型的完整範例,請參閱 PSFSample

讓我們逐步解說在解決方案中建立及設定這些專案的步驟。

建立封裝解決方案

如果您的桌面應用程式還沒有解決方案,請在 Visual Studio 中建立新的空白解決方案

空白解決方案

您也可能想要新增任何您擁有的應用程式專案。

新增封裝專案

如果您還沒有Windows 應用程式封裝專案,請建立一個,並將其新增至您的方案。

封裝專案範本

如需 Windows 應用程式封裝專案的詳細資訊,請參閱使用 Visual Studio 封裝您的應用程式

方案總管中,以滑鼠右鍵按一下封裝專案,選取 [ 編輯],然後將此專案新增至專案檔的底部:

<Target Name="PSFRemoveSourceProject" AfterTargets="ExpandProjectReferences" BeforeTargets="_ConvertItems">
<ItemGroup>
  <FilteredNonWapProjProjectOutput Include="@(_FilteredNonWapProjProjectOutput)">
  <SourceProject Condition="'%(_FilteredNonWapProjProjectOutput.SourceProject)'=='<your runtime fix project name goes here>'" />
  </FilteredNonWapProjProjectOutput>
  <_FilteredNonWapProjProjectOutput Remove="@(_FilteredNonWapProjProjectOutput)" />
  <_FilteredNonWapProjProjectOutput Include="@(FilteredNonWapProjProjectOutput)" />
</ItemGroup>
</Target>

加入執行時間修正的專案

將 c + + 動態連結程式庫 (DLL) 專案加入至方案。

執行時間修正程式庫

以滑鼠右鍵按一下該專案,然後選擇 [ 屬性]。

在 [屬性] 頁面中,尋找 [ c + + 語言標準 ] 欄位,然後在該欄位旁的下拉式清單中,選取 [ ISO c + + 17 標準 (/std: c + + 17]) 選項。

ISO 17 選項

以滑鼠右鍵按一下該專案,然後在內容功能表中,選擇 [ 管理 Nuget 封裝 ] 選項。 確定 [ 套件來源 ] 選項設定為 [ 全部 ] 或 [ nuget.org]。

按一下該欄位旁的設定圖示。

搜尋 .psf* Nuget 套件,然後針對此專案進行安裝。

nuget 套件

如果您想要偵測或擴充現有的執行時間修正,請使用本指南的「 尋找執行時間修正 」一節中所述的指導方針,加入您取得的執行時間修正檔案。

如果您想要建立全新的修正程式,請不要將任何專案新增至此專案。 稍後在本指南中,我們將協助您將正確的檔案新增至此專案。 現在,我們將繼續設定您的解決方案。

新增啟動 .psf Launcher 可執行檔的專案

將 c + +空白 Project專案加入至方案。

空白專案

使用上一節所述的相同指導方針,將 .Psf Nuget 套件新增至此專案。

開啟專案的屬性頁,然後在 [ 一般 設定] 頁面中,將 [ 目標名稱 ] 屬性設定為 或, 視您應用程式的架構而定。

.psf Launcher 參考

將專案參考新增至方案中的執行時間修正專案。

執行時間修正參考

以滑鼠右鍵按一下參考,然後在 [ 屬性 ] 視窗中,套用這些值。

屬性
複製到本機 True
複製附屬組件到本機 True
參考組件輸出 True
連結程式庫相依性 False
程式庫相依性輸入 False

設定封裝專案

在封裝專案的 \[應用程式\] 資料夾上按一下滑鼠右鍵,然後選擇 \[加入參考\]

新增專案參考

選擇 [.psf Launcher 專案和您的桌面應用程式專案,然後選擇 [確定]按鈕。

傳統型專案

注意

如果您的應用程式沒有原始程式碼,只要選擇 .psf Launcher 專案即可。 當您建立設定檔時,我們會示範如何參考您的可執行檔。

在 [應用程式] 節點中,以滑鼠右鍵按一下 .psf Launcher 應用程式,然後選擇 [設定為進入點]。

設定進入點

將名為的檔案新增 config.json 至您的封裝專案,然後複製下列 json 文字並貼到檔案中。 將 [ 封裝動作 ] 屬性設定為 [ 內容]。

{
    "applications": [
        {
            "id": "",
            "executable": "",
            "workingDirectory": ""
        }
    ],
    "processes": [
        {
            "executable": "",
            "fixups": [
                {
                    "dll": "",
                    "config": {
                    }
                }
            ]
        }
    ]
}

提供每個索引鍵的值。 請使用下表作為指南。

Array 索引鍵
應用程式所需 id IdApplication 封裝資訊清單中使用元素的屬性值。
應用程式所需 可執行檔 您要啟動之可執行檔的封裝相對路徑。 在大部分的情況下,您可以在修改之前從套件資訊清單檔中取得此值。 這是元素的屬性值 ExecutableApplication
應用程式所需 workingDirectory (選擇性) 封裝相對路徑,用來做為啟動應用程式的工作目錄。 如果您未設定此值,作業系統會使用該 System32 目錄作為應用程式的工作目錄。
處理程序 可執行檔 在大部分的情況下,這會是上述設定的名稱, executable 並移除路徑和副檔名。
修復 dll 要載入之修復 DLL 的封裝相對路徑。
修復 config (選擇性) 控制修復 DLL 的運作方式。 此值的確切格式會因修復修復而異,因為每個修復可以視需要解讀此「blob」。

當您完成時,您的檔案 config.json 看起來會像這樣。

{
  "applications": [
    {
      "id": "DesktopApplication",
      "executable": "DesktopApplication/WinFormsDesktopApplication.exe",
      "workingDirectory": "WinFormsDesktopApplication"
    }
  ],
  "processes": [
    {
      "executable": ".*App.*",
      "fixups": [ { "dll": "RuntimeFix.dll" } ]
    }
  ]
}

注意

applicationsprocesses 和索引 fixups 鍵是陣列。 這表示您可以使用 config.xml 檔案指定一個以上的應用程式、進程和修復 DLL。

偵錯工具執行時間修正

在 Visual Studio 中,按 F5 啟動偵錯工具。 首先,第一件事是 .psf Launcher 應用程式,後者接著會啟動您的目標桌面應用程式。 若要對目標傳統型應用程式進行偵錯工具,您必須選擇 [ debug 附加至進程],然後選取應用程式進程,以手動方式附加至桌面應用程式進程。 若要允許使用原生執行時間修正 DLL 來進行 .NET 應用程式的偵錯工具,請選取 managed 和機器碼類型 (混合模式的偵錯工具) 。

設定好之後,您可以在桌面應用程式程式碼和執行時間修正專案的程式程式碼旁設定中斷點。 如果您沒有應用程式的原始程式碼,您只能將中斷點設定在執行時間修正專案的程式程式碼旁邊。

因為 F5 偵錯工具會從封裝配置資料夾路徑部署鬆散式檔案來執行應用程式,而不是從 msix/.appx 套件進行安裝,所以 layout 資料夾通常與安裝的封裝資料夾沒有相同的安全性限制。 因此,在套用執行時間修正之前,可能無法重現套件路徑存取拒絕錯誤。

若要解決此問題,請使用 msix/.appx 套件部署,而不是 F5 鬆散檔案部署。 若要建立 msix/.appx 封裝檔案,請使用 Windows SDK 中的MakeAppx公用程式,如上面所述。 或者,從 Visual Studio 中,以滑鼠右鍵按一下您的應用程式專案節點,然後選取 [儲存- 建立應用程式套件]。

Visual Studio 的另一個問題是,它沒有內建的支援,無法附加至偵錯工具啟動的任何子進程。 這會讓您很難在目標應用程式的啟動路徑中偵測邏輯,必須在啟動後以手動方式附加 Visual Studio。

若要解決這個問題,請使用支援子進程附加的偵錯工具。 請注意,通常不能將即時 (JIT) 偵錯工具附加至目標應用程式。 這是因為大部分的 JIT 技術都牽涉到透過 ImageFileExecutionOptions 登錄機碼來啟動偵錯工具,以取代目標應用程式。 這會破壞 PSFLauncher.exe 用來將 FixupRuntime.dll 插入目標應用程式的 detouring 機制。 WinDbg (包含在Windows 的偵錯工具中,並從Windows SDK取得)支援子進程附加。 它現在也支援直接 啟動和偵測 UWP 應用程式

若要將目標應用程式啟動以子進程的形式啟動,請開始 WinDbg

windbg.exe -plmPackage PSFSampleWithFixup_1.0.59.0_x86__7s220nvg1hg3m -plmApp PSFSample

出現 WinDbg 提示時,啟用子調試,並設定適當的中斷點。

.childdbg 1
g

(會在目標應用程式啟動並中斷偵錯工具之前執行)

sxe ld fixup.dll
g

(執行到載入修復 DLL 之後)

bp ...

注意

PLMDebug也可用來在啟動時,將偵錯工具附加至應用程式,也會包含在Windows 的調試程式中。 但是,使用的方式比 WinDbg 現在提供的直接支援更複雜。

支援

有任何問題嗎? 請在 MSIX 技術小組網站上詢問我們 套件支援架構 交談空間的問題。