包支持框架-文件系统写入权限修正Package Support Framework - Filesystem Write Permission fixup

调查Investigation

Windows 应用会将与应用程序相关的特定目录重定向到 Windows 应用容器文件夹。Windows Apps will redirect specific directories that are related to the application to the Windows App container folder. 如果应用程序尝试写入 Windows 应用容器,将触发一个错误,并且写入会失败。If an application attempts to write to the Windows App container, an error will trigger, and the write will fail.

使用包支持框架 (PSF) ,可以对 Windows 应用包进行增强以解决此问题。Using the Package Support Framework (PSF), enhancements can be made to the Windows App package to resolve this issue. 首先,必须确定应用程序请求的失败和目录路径。First, we must identify the failure, and directory paths that are being requested by the app.

捕获 Windows 应用失败Capture the Windows App Failure

筛选结果是一个可选的步骤,它会使查看与应用程序相关的故障变得更加容易。Filtering the results is an optional step, that will make viewing application related failures easier. 为此,我们将创建两个筛选器规则。To do this, we will create two filter rules. 应用程序进程名称的第一个 include 筛选器,第二个包含不成功的结果。The first an include filter for the application process name, and the second is an inclusion of any results that are not successful.

  1. 下载 SysInternals 进程监视器 并将其提取到 C:\PSF\ProcessMonitor 目录。Download and extract the SysInternals Process Monitor to the C:\PSF\ProcessMonitor directory.
  2. 打开 Windows 资源管理器并导航到已提取的 SysInternals 进程监视文件夹Open Windows Explorer and navigate to the extracted SysInternals Process Monitor Folder
  3. 双击 SysInternals 进程监视器 ( # A0) 文件,然后启动应用程序。Double-click the SysInternals Process Monitor (procmon.exe) file, launching the app.
  4. 如果出现 UAC 提示,请选择 " 是" 按钮。If prompted by UAC, select the Yes button.
  5. 在 "进程监视器筛选器" 窗口中,选择标记为 " 体系结构" 的第一个下拉菜单。In the Process Monitor Filter Window, select the first drop-down menu labeled with Architecture.
  6. 从下拉菜单中选择 " 进程名称 "。Select Process Name from the drop-down menu.
  7. 在下一个下拉菜单中,验证是否已将其设置为的值 In the next drop-down menu, verify that it is set with the value of is.
  8. 在 "文本" 字段中,键入应用的进程名称 (例如: PSFSample.exe) 。In the text field type the process name of your App (Example: PSFSample.exe). 具有应用名称的进程监视器筛选器窗口的示例
  9. 选择“添加”按钮。Select the Add button.
  10. 在 "进程监视器筛选器" 窗口中,选择标记为 " 进程名称" 的第一个下拉菜单。In the Process Monitor Filter Window, select the first drop-down menu labeled Process Name.
  11. 从下拉菜单中选择 " 结果 "。Select Result from the drop-down menu.
  12. 在下一个下拉菜单中选择该菜单,并从下拉菜单中选择 " 不是 "。In the next drop-down menu, select it, and select is not from the drop-down menu.
  13. 在 "文本" 字段中,键入: SUCCESSIn the text field type: SUCCESS. 带有结果的进程监视器筛选器窗口的示例
  14. 选择“添加”按钮。Select the Add button.
  15. 选择 " 确定" 按钮。Select the Ok button.
  16. 启动 Windows 应用程序,触发错误,然后关闭 Windows 应用程序。launch the Windows App, trigger the error, and close the Windows App.

查看 Windows 应用程序故障日志Review the Windows App Failure Logs

捕获 Windows 应用进程后,将需要对结果进行调查,以确定失败是否与工作目录相关。After capturing the Windows App processes, the results will need to be investigated to identify if the failure is related to the working directory.

  1. 查看 SysInternals Process Monitor 结果,搜索上表中列出的故障。Review the SysInternals Process Monitor results, searching for failures outlined in the above table.
  2. 如果结果显示 "找不到名称" 的结果,并将特定应用程序的详细信息 "Desired Access: ..." 作为目标,该应用的目标是 "C:\Program Files\WindowsApps \ ... \ " (,如下图所示) ,然后你已成功地识别了与工作目录相关的故障,请使用 PSF 支持文件系统访问 一文,获取有关如何将 PSF 更正应用到应用的指南。If the results show an "Name Not Found" result, with the details "Desired Access: ..." for your specific app targeting a directory outside of the "C:\Program Files\WindowsApps\...\" (as seen in the below image), then you have successfully identified a failure related with the working directory, use the PSF Support - Filesystem Access article for guidance on how to apply the PSF correction to your app. 在 SysInternals 进程监视器中显示错误消息观察到,以了解未能写入目录。

解决方法Resolution

Windows 应用会将与应用程序相关的特定目录重定向到 Windows 应用容器文件夹。Windows Apps will redirect specific directories that are related to the application to the Windows App container folder. 如果应用程序尝试写入 Windows 应用容器,将触发一个错误,并且写入会失败。If an application attempts to write to the Windows App container, an error will trigger, and the write will fail.

若要解决与 Windows 应用未能写入 Windows 应用容器相关的问题,必须执行以下四个步骤:To resolve the issue related to the Windows App failing to write to the Windows App container, we must follow the following four steps:

  1. 将 Windows 应用暂存到本地目录Stage the Windows App to a local directory
  2. 创建 Config.js并插入所需的 PSF 文件Create the Config.json and inject required PSF Files
  3. 更新 Windows 应用 Appxmanifest.xml 文件Update the Windows App AppxManifest file
  4. 对 Windows 应用进行重新打包和签名Repackage and sign the Windows App

上述步骤介绍了如何将 Windows 应用的内容提取到本地暂存目录,将 PSF 修正文件注入到暂存的 Windows 应用目录中,将应用程序启动器配置为指向 PSF 启动器,然后配置文件上的 PSF config.js,将 PSF 启动器重定向到指定工作目录的应用。The above steps provide guidance through extracting the content of the Windows App to a local staged directory, injecting the PSF fixup files into the staged Windows App directory, configuring the Application Launcher to point to the PSF launcher, then configuring the PSF config.json file to redirect the PSF launcher to the app specifying the working directory.

下载并安装所需的工具Download and Install Required Tools

此过程将指导你完成以下工具的检索和使用:This process will guide you through the retrieval of, and usage of the following tools:

  • NuGet 客户端工具NuGet Client Tool
  • 包支持框架Package Support Framework
  • Windows 10 SDK (最新版本) Windows 10 SDK (latest version)
  • SysInternals 进程监视器SysInternals Process Monitor

下面将提供有关下载和安装所需工具的分步指导。The following will provide step-by-step guidance on downloading and installing the required tools.

  1. 下载最新的 (非预览版) 版本的 NuGet 客户端工具,并将 nuget.exe 保存在 C:\PSF\nuget 文件夹中。Download the latest (non-preview) version of the NuGet client tool, and save the nuget.exe in the C:\PSF\nuget folder.

  2. 通过从管理 PowerShell 窗口运行以下内容,使用 Nuget 下载包支持框架:Download the Package Support Framework using Nuget by running the following from an Administrative PowerShell window:

    Set-Location "C:\PSF"
    .\nuget\nuget.exe install Microsoft.PackageSupportFramework
    
  3. 下载并安装 Windows 10 软件开发工具包 (Win 10 SDK) Download and install the Windows 10 Software Development Toolkit (Win 10 SDK).

    1. 下载 Win 10 SDKDownload the Win 10 SDK.
    2. 运行上一步中下载的 winsdksetup.exeRun the winsdksetup.exe that was downloaded in the previous step.
    3. 选择“下一步”按钮。Select the Next button.
    4. 仅选择以下三个安装功能:Select only the following three features for install:
      • 适用于桌面应用的 Windows SDK 签名工具Windows SDK Signing Tools for Desktop Apps
      • 适用于 UWP C++ 应用的 Windows SDKWindows SDK for UWP C++ Apps
      • 适用于 UWP 应用本地化的 microsoft azure SDKWindwos SDK for UWP Apps Localization
    5. 选择“安装”按钮 。Select the Install button.
    6. 选择 " 确定" 按钮。Select the Ok button.

暂存 Windows 应用Stage the Windows App

通过暂存 Windows 应用,我们将在本地目录中提取/unpackaging Windows 应用程序的内容。By staging the Windows App, we will be extracting / unpackaging the contents of the Windows App to a local directory. 将 Windows 应用解包到暂存位置后,可以注入 PSF 修正文件,以更正任何不需要的体验。Once the Windows App has been unpacked to the staging location, PSF fixup files can be injected correcting any unwanted experiences.

  1. 打开管理 PowerShell 窗口。Open an Administrative PowerShell window.

  2. 针对特定的应用程序文件和 Windows 10 SDK 版本设置以下变量:Set the following variables targeting your specific app file, and Windows 10 SDK version:

    $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
    
  3. 通过运行以下 PowerShell cmdlet,将 Windows 应用解压缩到暂存文件夹:Unpack the Windows App to the staging folder by running the following PowerShell cmdlet:

    ## 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 文件Create and inject required PSF Files

若要将更正操作应用于 Windows 应用程序,必须创建一个 config.js 文件,并将其提供给有关 Windows 应用程序启动器失败的信息。To apply corrective actions to the Windows App the a config.json file must be created, and supplied with information about the Windows App Launcher that is failing. 如果有多个 Windows 应用程序启动器遇到问题,则可以用多个条目更新文件 上的config.jsIf there are multiple Windows App Launchers that are experiencing issues, the config.json file can be updated with multiple entries.

更新文件 上的config.js 后,必须将文件中的 config.js 和支持的 PSF 修正文件移到 Windows 应用包的根目录中。After updating the config.json file, the config.json file and supporting PSF fixup files must then be moved into the root of the Windows App package.

  1. Visual Studio Code (VS Code ") " 或任何其他文本编辑器中打开。Open Visual Studio Code (VS Code), or any other text editor.

  2. 通过选择 "VS Code 顶部的" 文件 "菜单,然后从下拉菜单中选择" 新建文件 ",创建一个新的文件。Create a new file, by selecting the File menu at the top of the VS Code, selecting New File from the drop-down menu.

  3. 将该文件另存为 config.js在上,选择 "VS Code" 窗口顶部的 " 文件 " 菜单,从下拉菜单中选择 " 保存 "。Save the file as config.json, by select the File menu at the top of the VS Code window, selecting Save from the drop-down menu. 在 "另存为" 窗口中,导航到 (C:\PSF\Staging\PSFSampleApp) 的 Windows 应用暂存目录,并将 文件名 设置为 config.jsonIn the Save As window, navigate to the Windows App Staging directory (C:\PSF\Staging\PSFSampleApp) and set the File Name as config.json. 选择“保存”按钮。Select the Save button.

  4. 将以下代码复制到新创建的文件 config.jsCopy the following code to the newly created config.json file.

    {
        "applications": [
            {
                "id": "",
                "executable": ""
            }
        ],
        "processes": [
            {
                "executable": "",
                "fixups": [
                {
                    "dll": "",
                    "config": {
                        "redirectedPaths": {
                            "packageRelative": [
                                {
                                    "base": "",
                                    "patterns": [
                                        ""
                                    ]
                                }
                            ]
                        }
                    }
                }
            ]
            }
        ]
    }
    
  5. 使用 VS Code 或其他文本编辑器打开位于 Windows 应用暂存文件夹 (C:\PSF\Staging\PSFSampleApp\AppxManifest.xml) 的暂存的 Windows 应用程序 appxmanifest.xml 文件。Open the staged Windows App AppxManifest file located in the Windows App staging folder (C:\PSF\Staging\PSFSampleApp\AppxManifest.xml) using VS Code, or another text editor.

    <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>
    
  6. applications.id config.js 中的值设置为与 AppxManifest.xml 文件的 " Applications.Application.ID " 字段中找到的值相同的值。Set the applications.id value in the config.json to be the same value as found in the Applications.Application.ID field of the AppxManifest.xml file. 向 Appxmanifest.xml 文件中的 ID 位置旋转图像。

  7. applications.executable config.js上 的值设置为面向位于 AppxManifest.xml 文件 Applications.Application.Executable 字段中的应用程序的相对路径。Set the applications.executable value in the config.json to target the relative path to the application located in Applications.Application.Executable field of the AppxManifest.xml file. 向 Appxmanifest.xml 文件中的可执行文件的位置旋转图像。

  8. applications.workingdirectory config.js上 的值设置为面向 AppxManifest.xml 文件的 Applications.Application.Executable 字段中找到的相对文件夹路径。Set the applications.workingdirectory value in the config.json to target the relative folder path found in the Applications.Application.Executable field of the AppxManifest.xml file. 在 Appxmanifest.xml 文件中对工作目录的位置进行了旋转。

  9. process.executable config.js上 的值设置为以 (在 AppxManifest.xml 文件的 Applications.Application.Executable 字段中找不到) 路径和扩展名的文件名。Set the process.executable value in the config.json to target the file name (without path and extensions) found in the Applications.Application.Executable field of the AppxManifest.xml file. 图像:在 Appxmanifest.xml 文件中将进程可执行文件的位置圈起来。

  10. processes.fixups.dll config.js上 的值设置为以特定于体系结构的 FileRedirectionFixup.dll 为目标。Set the processes.fixups.dll value in the config.json to target the architecture specific FileRedirectionFixup.dll. 如果更正适用于 x64 体系结构,请将值设置为 FileRedirectionFixup64.dllIf correction is for x64 architecture, set the value to be FileRedirectionFixup64.dll. 如果体系结构为 x86 或未知,请将值设置为 FileRedirectionFixup86.dllIf the architecture is x86, or is unknown, set the value to be FileRedirectionFixup86.dll

  11. processes.fixups.config.redirectedPaths.packageRelative.base config.js上 的值设置为包相对文件夹路径,如 AppxManifest.xml 文件的 Applications.Application.Executable 中所示。Set the processes.fixups.config.redirectedPaths.packageRelative.base value in the config.json to the package relative folder path as found in the Applications.Application.Executable of the AppxManifest.xml file. 在 Appxmanifest.xml 文件中对工作目录的位置进行了旋转。

  12. 设置 processes.fixups.config.redirectedPaths.packageRelative.patterns " config.js上 的" 文件中的值,以匹配应用程序正在创建的文件类型。Set the processes.fixups.config.redirectedPaths.packageRelative.patterns value in the config.json file to match the file type being created by the application. 通过使用 ". * \ .log" ,PSF 将重定向对 packageRelative 路径和子目录中 processes.fixups.config 标识的目录中所有日志文件的写入。By using ".*\.log" the PSF will redirect writes for all log files that are in the directory identified in the processes.fixups.config.redirectedPaths.packageRelative.base path, as well as child directories.

  13. 保存更新的 config.js 文件。Save the updated config.json file.

    {
        "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"
                                        ]
                                    }
                                ]
                            }
                        }
                    }
                ]
            }
        ]
    }
    
  14. 将以下四个文件从基于应用程序可执行文件体系结构的包支持框架复制到暂存的 Windows 应用程序的根目录。Copy the following four files from the Package Support Framework based on the application executable architecture to the root of the staged Windows App. 以下文件位于 .\Microsoft.PackageSupportFramework. 中。\binThe following files are located within the .\Microsoft.PackageSupportFramework.\bin.

    应用程序 (x64) Application (x64) X86 (的应用程序) Application (x86)
    PSFLauncher64.exePSFLauncher64.exe PSFLauncher32.exePSFLauncher32.exe
    PSFRuntime64.dllPSFRuntime64.dll PSFRuntime32.dllPSFRuntime32.dll
    PSFRunDll64.exePSFRunDll64.exe PSFRunDll32.exePSFRunDll32.exe
    FileRedirectionFixup64.dllFileRedirectionFixup64.dll FileRedirectionFixup64.dllFileRedirectionFixup64.dll

更新 Appxmanifest.xmlUpdate AppxManifest

创建和更新文件 上的config.js 后,必须针对 config.js上 包含的每个 windows 应用程序启动器更新 windows 应用程序的 AppxManifest.xmlAfter creating and updating the config.json file, the Windows App's AppxManifest.xml must be updated for each Windows App Launcher that was included in the config.json. Appxmanifest.xml 的应用程序现在必须针对与应用程序体系结构关联的 PSFLauncher.exeThe AppxManifest's Applications must now target the PSFLauncher.exe associated with the applications architecture.

  1. 打开文件资源管理器,然后导航到暂存的 .MSIX 应用程序文件夹 (C:\PSF\Staging\PSFSampleApp) 。Open File Explorer, and navigate to the Staged MSIX App folder (C:\PSF\Staging\PSFSampleApp).

  2. 右键单击 " AppxManifest.xml",然后从 (下拉菜单中选择 "从 代码打开 " (可选),可以通过其他文本编辑器) 打开。Right-click on AppxManifest.xml, and select Open with Code from the drop-down menu (Optionally, you can open with another text editor).

  3. 更新 AppxManifest.xml 文件,其中包含以下信息:Update the AppxManifest.xml file with the following information:

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

重新打包应用程序Re-package the application

已应用所有更正,现在可以将 Windows 应用重新打包到 .MSIX 中,并使用代码签名证书对其进行签名。All of the corrections have been applied, now the Windows App can be re-packaged into an MSIX and signed using a code signing certificate.

  1. 打开管理 PowerShell 窗口。Open an Administrative PowerShell Window.

  2. 设置以下变量:Set the following variables:

    $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 应用:Repack the Windows App from the staging folder by running the following PowerShell cmdlet:

    Set-Location "${env:ProgramFiles(x86)}\Windows Kits\10\Bin\$Win10SDKVersion\$OSArchitecture"
    .\makeappx.exe pack /p "$AppPath" /d "$StagingFolder"
    
  4. 通过运行以下 PowerShell cmdlet 为 Windows 应用签名:Sign the Windows App by running the following PowerShell cmdlet:

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