如何修正套件支援架構檔案系統寫入權限錯誤

本文說明如何使用套件支援架構 (PSF) 來解決檔案系統寫入權限錯誤。

Windows 應用程式會將特定應用程式相關目錄重新導向至 C:\Program Files\WindowsApps 資料夾。 如果應用程式嘗試寫入 Windows 應用程式容器,就會觸發錯誤,而寫入會失敗。 您可以對 Windows 應用程式套件進行增強功能,以解決此問題。

調查

首先,識別失敗,以及應用程式所要求的目錄路徑。

擷取 Windows 應用程式失敗

篩選結果是選擇性的,但可讓您更輕鬆地查看應用程式相關的失敗。 若要篩選結果,您可以建立兩個篩選規則。 第一個篩選包含應用程式進程名稱,而第二個篩選準則包含任何不成功的結果。

  1. SysInternals 進程監視器 下載並解壓縮至 C:\PSF\ProcessMonitor 目錄。

  2. 開啟 Windows 檔案總管並流覽至擷取的 SysInternals ProcessMonitor 資料夾。

  3. 選取 [SysInternals 進程監視器 ]procmon.exe 檔案以啟動應用程式。

  4. 如果 UAC 出現提示,請選取 [ ]。

  5. 在 [ 進程監視器篩選] 視窗中,從第一個欄位的下拉式功能表中選取 [ 進程名稱 ]。

  6. 確認 出現在 下一個欄位中。

  7. 在下一個欄位中,輸入應用程式的進程名稱,例如 PSFSample.exe

    應用程式名稱為 [進程監視器篩選] 視窗的範例。

  8. 選取 [新增]。

  9. 在 [ 進程監視器篩選] 視窗中,從第一個欄位的下拉式功能表中選取 [ 結果 ]。

  10. 在下一個欄位中,選取 不是 從下拉式功能表中選取。

  11. 在文字欄位中,輸入 SUCCESS

    [進程監視器篩選] 視窗與 [結果] 的範例。

  12. 選取 [新增],然後選取 [確定]

  13. 啟動 Windows 應用程式、觸發錯誤,然後關閉 Windows 應用程式。

檢閱 Windows 應用程式失敗記錄

擷取 Windows 應用程式進程之後,請調查結果,以判斷失敗是否與工作目錄有關。

檢閱 SysInternals 進程監視器失敗結果。 如果結果包含 拒絕存取,且具有 Desired Access:Generic Write 詳細資料,針對以 C:\Program Files\WindowsApps\...\為目標的應用程式,您發現與工作目錄相關的寫入權限失敗。

顯示 SysInternals 進程監視器中見證的錯誤訊息,無法寫入目錄。

如果您識別此錯誤,請將下列 PSF 更正套用至您的應用程式。

解決方案

若要解決 Windows 應用程式無法寫入 Windows 應用程式容器的問題,請遵循下列步驟:

  1. 將 Windows 應用程式的內容解壓縮到 本機臨時目錄
  2. 建立 config.json,並將 PSF 修正檔案插入 分段 Windows 應用程式目錄。
  3. 將應用程式啟動器設定為指向 PSF 啟動器,並設定 PSF config.json 檔案以重新導向 PSF 啟動器,並指定工作目錄。
  4. 更新 Windows 應用程式 AppxManifest 檔案
  5. 重新封裝並簽署 Windows 應用程式

下載並安裝必要的工具

此程式需要下列工具:

  • NuGet 用戶端工具
  • 套件支援架構 (PSF)
  • Windows 10軟體發展工具組 (Win 10 SDK) ,最新版本
  • SysInternals 進程監視器

若要下載並安裝 NuGet 和 PSF:

  1. 下載 NuGet 用戶端工具的最新非預覽版本,並將 nuget.exe 儲存在 C:\PSF\nuget中。

  2. 從系統管理 PowerShell 視窗執行下列命令,以使用 NuGet 下載並安裝套件支援架構:

    Set-Location "C:\PSF"
    .\nuget\nuget.exe install Microsoft.PackageSupportFramework
    

若要下載並安裝Windows 10 SDK:

  1. 下載 Win 10 SDK
  2. 執行 winsdksetup.exe
  3. 選取 [下一步]。
  4. 只選取下列三個功能:
    • 適用于傳統型應用程式的 Windows SDK 簽署工具
    • 適用于 UWP C++ 應用程式的 Windows SDK
    • 適用于 UWP Apps 當地語系化的 Windwos SDK
  5. 選取 [安裝],然後選取 [ 確定]。

暫存 Windows 應用程式

暫存 Windows 應用程式會將應用程式的內容解壓縮並解壓縮到本機目錄。 將 Windows 應用程式解壓縮到預備位置之後,您可以插入 PSF 修正檔案以更正任何不必要的體驗。

  1. 在系統管理 PowerShell 視窗中,將下列變數設定為以特定應用程式檔案為目標,並Windows 10 SDK 版本:

    $AppPath          = "C:\PSF\SourceApp\PSFSampleApp.msix"         ## Path to the MSIX App Installer
    $StagingFolder    = "C:\PSF\Staging\PSFSampleApp"                ## Path to where the MSIX App will be staged
    $OSArchitecture   = "x$((gwmi Win32_Processor).AddressWidth)"    ## Operating System Architecture
    $Win10SDKVersion  = "10.0.19041.0"                               ## Latest version of the Win10 SDK
    
  2. 執行下列 PowerShell Cmdlet,將 Windows 應用程式解壓縮到暫存資料夾:

    ## Sets the directory to the Windows 10 SDK
    Set-Location "${env:ProgramFiles(x86)}\Windows Kits\10\Bin\$Win10SDKVersion\$OSArchitecture"
    
    ## Unpackages the Windows app to the staging folder
    .\makeappx.exe unpack /p "$AppPath" /d "$StagingFolder"
    

建立並插入必要的 PSF 檔案

若要更正 Windows 應用程式,您可以建立 config.json 檔案,其中包含失敗之 Windows 應用程式啟動器的相關資訊。 如果有多個 Windows 應用程式啟動器發生問題,您可以使用多個專案來設定 config.json 檔案。

建立 config.json 檔案之後,您會將 config.json 和支援 PSF 修正檔案移至 Windows 應用程式套件的根目錄。

  1. 開啟Visual Studio Code或其他文字編輯器。

  2. 在 Windows 應用程式預備目錄中建立名為 config.json 的新檔案 C:\PSF\Staging\PSFSampleApp

  3. 將下列程式碼複製到新建立 的 config.json 檔案。

    {
        "applications": [
            {
                "id": "",
                "executable": ""
            }
        ],
        "processes": [
            {
                "executable": "",
                "fixups": [
                {
                    "dll": "",
                    "config": {
                        "redirectedPaths": {
                            "packageRelative": [
                                {
                                    "base": "",
                                    "patterns": [
                                        ""
                                    ]
                                }
                            ]
                        }
                    }
                }
            ]
            }
        ]
    }
    
  4. 在 Windows 應用程式暫存資料夾中開啟 AppxManifest.xml 檔案。 下列範例顯示 AppxManifest.xml 檔案:

    <Applications>
        <Application Id="PSFSAMPLE" Executable="VFS\ProgramFilesX64\PS Sample App\PSFSample.exe" EntryPoint="Windows.FullTrustApplication">
        <uap:VisualElements BackgroundColor="transparent" DisplayName="PSFSample" Square150x150Logo="Assets\StoreLogo.png" Square44x44Logo="Assets\StoreLogo.png" Description="PSFSample">
            <uap:DefaultTile Wide310x150Logo="Assets\StoreLogo.png" Square310x310Logo="Assets\StoreLogo.png" Square71x71Logo="Assets\StoreLogo.png" />
        </uap:VisualElements>
        </Application>
    </Applications>
    
  5. config.json 檔案中進行下列變更:

    • applications.id 值設定為與 Applications.Application.IDAppxManifest.xml 檔案欄位中的值相同。

      顯示 AppxManifest 檔案中識別碼位置的影像。

    • applications.executable 值設定為以位於 Applications.Application.ExecutableAppxManifest.xml 檔案欄位中的應用程式相對路徑為目標。

      顯示 *AppxManifest.xml* 檔案中可執行檔位置的影像。

    • applications.workingdirectory 值設定為以AppxManifest.xml檔案欄位中的相對資料夾路徑 Applications.Application.Executable 為目標。

      顯示 AppxManifest 檔案中工作目錄位置的影像。

    • AppxManifest.xml檔案的欄位中, Applications.Application.Executableprocess.executable 值設定為以檔案名為目標,而不需路徑和副檔名。

      顯示 AppxManifest 檔案中進程可執行檔位置的影像。

    • processes.fixups.dll 值設定為以架構特定的 FileRedirectionFixup.dll 為目標。 如果更正是 x64 架構,請將值設定為 FileRedirectionFixup64.dll 。 如果架構為 x86 或未知,請將值設定為 FileRedirectionFixup86.dll

    • processes.fixups.config.redirectedPaths.packageRelative.base 值設定為AppxManifest.xml檔案欄位中的套件相對資料夾路徑 Applications.Application.Executable

      顯示 AppxManifest 檔案中工作目錄位置的影像。

    • processes.fixups.config.redirectedPaths.packageRelative.patterns設定值以符合應用程式建立的檔案類型。 如果您使用 .*\\.log ,PSF 會將目錄和子目錄中的所有記錄檔寫入 processes.fixups.config.redirectedPaths.packageRelative.base 重新導向。

  6. 儲存更新的 config.json 檔案。 下列範例顯示更新 的 config.json 檔案:

    {
        "applications": [
            {
            "id": "PSFSample",
            "executable": "VFS/ProgramFilesX64/PS Sample App/PSFSample.exe"
            }
        ],
        "processes": [
            {
                "executable": "PSFSample",
                "fixups": [
                    {
                        "dll": "FileRedirectionFixup64.dll",
                        "config": {
                            "redirectedPaths": {
                                "packageRelative": [
                                    {
                                        "base": "VFS/ProgramFilesX64/PS Sample App/",
                                        "patterns": [
                                            ".*\\.log"
                                        ]
                                    }
                                ]
                            }
                        }
                    }
                ]
            }
        ]
    }
    
  7. 將下列檔案從應用程式可執行檔架構的套件支援架構複製到分段 Windows 應用程式的根目錄。 您可以在.\Microsoft.PackageSupportFramework.\Version > \ < bin中找到檔案。

    應用程式 (x64) 應用程式 (x86)
    PSFLauncher64.exe PSFLauncher32.exe
    PSFRuntime64.dll PSFRuntime32.dll
    PSFRunDll64.exe PSFRunDll32.exe
    FileRedirectionFixup64.dll FileRedirectionFixup64.dll

更新 AppxManifest

建立並更新config.json檔案之後,請針對config.json中包含的每個 Windows 應用程式啟動器更新 Windows 應用程式的AppxManifest.xml檔案。 AppxManifest.xmlApplications 現在必須以與應用程式架構相關聯的PSFLauncher.exe為目標。

  1. 在暫存的 MSIX 應用程式資料夾中,開啟 AppxManifest.xmlC:\PSF\Staging\PSFSampleApp
  2. 使用下列程式碼更新 AppxManifest.xml
    <Package ...>
    ...
    <Applications>
        <Application Id="PSFSample"
                    Executable="PSFLauncher32.exe"
                    EntryPoint="Windows.FullTrustApplication">
        ...
        </Application>
    </Applications>
    </Package>
    

重新封裝應用程式

套用所有更正之後,請將 Windows 應用程式重新封裝到 MSIX,並使用程式碼簽署憑證簽署它。

  1. 開啟系統管理 PowerShell 視窗。

  2. 設定下列變數:

    $AppPath          = "C:\PSF\SourceApp\PSFSampleApp_Updated.msix" ## Path to the MSIX App Installer
    $CodeSigningCert  = "C:\PSF\Cert\CodeSigningCertificate.pfx"     ## Path to your code signing certificate
    $CodeSigningPass  = "<Password>"                                 ## Password used by the code signing certificate
    $StagingFolder    = "C:\PSF\Staging\PSFSampleApp"                ## Path to where the MSIX App will be staged
    $OSArchitecture   = "x$((gwmi Win32_Processor).AddressWidth)"    ## Operating System Architecture
    $Win10SDKVersion  = "10.0.19041.0"                               ## Latest version of the Win10 SDK
    
  3. 執行下列 PowerShell Cmdlet,從預備資料夾重新封裝 Windows 應用程式:

    Set-Location "${env:ProgramFiles(x86)}\Windows Kits\10\Bin\$Win10SDKVersion\$OSArchitecture"
    .\makeappx.exe pack /p "$AppPath" /d "$StagingFolder"
    
  4. 執行下列 PowerShell Cmdlet 來簽署 Windows 應用程式:

    Set-Location "${env:ProgramFiles(x86)}\Windows Kits\10\Bin\$Win10SDKVersion\$OSArchitecture"
    .\signtool.exe sign /v /fd sha256 /f $CodeSigningCert /p $CodeSigningPass $AppPath