開始使用套件支援架構

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

本文提供套件支援架構的每個元件,以及使用它的逐步指南。

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

套件支援架構包含可執行檔、運行時間管理員 DLL 和一組執行時間修正。

套件支援架構

以下是程式:

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

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

套件支援架構 DLL 插入

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

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

使用進程監視器來識別問題

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

ProcMon 應用程式篩選

隨即會出現事件清單。 對於其中許多事件, SUCCESS 一詞會出現在 [結果] 資料 行中。

ProcMon 事件

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

ProcMon 排除成功

如果您懷疑檔案系統存取失敗,請在 System32/SysWOW64 或套件檔案路徑下搜尋失敗的事件。 篩選也可以在這裡提供協助。 從此清單底部開始,然後向上捲動。 此清單底部出現的失敗最近發生。 請特別注意包含字串的錯誤,例如「拒絕存取」和「找不到路徑/名稱」,並忽略看起來不可疑的專案。 PSFSample有兩個問題。 您可以在下圖中顯示的清單中看到這些問題。

ProcMon Config.txt

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

應用程式Config.txt

第二個問題會出現在下圖中。

ProcMon Logfile

在此問題中,應用程式無法將 .log 檔案寫入其套件路徑。 這表示檔案重新導向修正可能會有説明。

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

PSF 包含您目前可以使用的執行時間修正程式,例如檔案重新導向修正。

檔案重新導向修正

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

例如,如果您的應用程式寫入與應用程式可執行檔位於相同目錄中的記錄檔,您可以使用 [檔案重新導向 修正 ] 在另一個位置建立該記錄檔,例如本機應用程式資料存放區。

來自社群的執行時間修正

請務必檢閱對 GitHub 頁面的社群貢獻。 其他開發人員可能已解決類似您的問題,並已共用執行時間修正程式。

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

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

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

讓我們逐一查看每個工作。

建立套件配置資料夾

如果您已經有 .msix (或 .appx) 檔案,您可以將內容解壓縮到配置資料夾中,做為套件的暫存區域。 您可以使用 MakeAppx 工具從命令提示字元執行這項操作,根據 SDK 的安裝路徑,您可以在Windows 10電腦上找到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 套件] 命令。 搜尋 Microsoft.PackageSupportFrameworkPSF 以尋找 Nuget.org 上的套件。然後,安裝它。

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

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

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

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

套件二進位檔

修改套件資訊清單

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

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

建立設定檔

建立檔案名 config.json ,並將該檔案儲存至套件的根資料夾。 修改 config.json 檔案的宣告應用程式識別碼,以指向您剛取代的可執行檔。 使用您從進程監視器取得的知識,您也可以設定工作目錄,以及使用檔案重新導向修正,將讀取/寫入重新導向至套件相對 「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"
                                    ]
                                }
                            ]
                        }
                    }
                }
            ]
        }
    ]
}

以下是 config.json 架構的指南:

Array 索引鍵
應用程式 識別碼 使用封裝資訊清單中專案之 屬性 Application 的值 Id
應用程式 可執行檔 您要啟動之可執行檔的套件相對路徑。 在大部分情況下,您可以在修改套件資訊清單檔案之前,先從套件資訊清單檔案取得此值。 Executable它是 專案的 屬性值 Application
應用程式 workingDirectory (選擇性) 封裝相對路徑,做為啟動之應用程式的工作目錄。 如果您未設定此值,作業系統會 System32 使用 目錄作為應用程式的工作目錄。
處理程序 可執行檔 在大部分情況下,這會是上述設定的名稱 executable ,其中已移除路徑和副檔名。
修正 dll 要載入之修正的套件相對路徑.msix/.appx。
修正 config (選擇性) 控制修正 dll 的運作方式。 此值的確切格式會依修正方式而有所不同,因為每個修正程式都可以將這個「Blob」解譯為想要的。

applicationsprocessesfixups 索引鍵是陣列。 這表示您可以使用 config.json 檔案來指定多個應用程式、進程和修正 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.json,然後封裝並安裝您的應用程式。

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

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

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

找不到 TraceShim 檔案

TraceShim 存取遭拒

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

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

  • 新增封裝專案
  • 新增執行時間修正的專案
  • 新增啟動 PSF 啟動器可執行檔的專案
  • 設定封裝專案

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

已完成的解決方案

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

Project 用途
DesktopApplicationPackage 此專案是以 Windows 應用程式封裝專案 為基礎,並輸出 MSIX 套件。
Runtimefix 這是 C++ Dynamic-Linked Library 專案,其中包含一或多個作為執行時間修正的取代函式。
PSFLauncher 這是 C++ 空白專案。 此專案是收集套件支援架構之執行時間可散發檔案的位置。 它會輸出可執行檔。 該可執行檔是您啟動解決方案時所執行的第一件事。
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 啟動器可執行檔的專案

將 C++ 空白專案 專案新增至方案。

空白專案

使用上一節所述的相同指引,將 PSF Nuget 套件新增至此專案。

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

PSF 啟動器參考

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

執行時間修正參考

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

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

設定封裝專案

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

新增專案參考

選擇 PSF 啟動器專案和傳統型應用程式專案,然後選擇 [ 確定 ] 按鈕。

傳統型專案

注意

如果您沒有應用程式的原始程式碼,只要選擇 PSF 啟動器專案即可。 我們將示範如何在建立組態檔時參考可執行檔。

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

設定進入點

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

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

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

Array 索引鍵
應用程式 識別碼 使用封裝資訊清單中專案之 屬性 Application 的值 Id
應用程式 可執行檔 您要啟動之可執行檔的套件相對路徑。 在大部分情況下,您可以在修改套件資訊清單檔案之前,先從套件資訊清單檔案取得此值。 Executable它是 專案的 屬性值 Application
應用程式 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" } ]
    }
  ]
}

注意

applicationsprocessesfixups 索引鍵是陣列。 這表示您可以使用 config.json 檔案來指定多個應用程式、進程和修正 DLL。

偵錯執行時間修正

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

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

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

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

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

若要解決此問題,請使用支援子進程附加的偵錯工具。 請注意,通常不可能將 Just-In-Time (JIT) 偵錯工具附加至目標應用程式。 這是因為大部分的 JIT 技術都牽涉到透過 ImageFileExecutionOptions 登錄機碼啟動偵錯工具來取代目標應用程式。 這會破壞PSFLauncher.exe用來將FixupRuntime.dll插入目標應用程式的導覽機制。 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 技術社群網站上的 套件支援架構 交談空間上詢問我們。