包支持框架 - 工作目录修复

调查

Windows应用会将与应用程序相关的特定目录重定向到Windows应用容器文件夹。 如果应用程序在安装过程中创建子文件夹 (C:\Program Files\Vendor\subfolder) ,稍后将调用此子文件夹,则找不到目录,因为它不存在。

使用包支持框架 (PSF) ,可以对Windows应用包进行增强以解决此问题。 首先,我们必须标识应用请求的失败和目录路径。

捕获Windows应用故障

筛选结果是一个可选步骤,可更轻松地查看与应用程序相关的故障。 为此,我们将创建两个筛选器规则。 应用程序进程名称的第一个包含筛选器,第二个是包含任何未成功的结果。

  1. 下载 SysInternals 进程监视器 并将其解压缩到 C:\PSF\ProcessMonitor 目录。
  2. 打开Windows资源管理器并导航到提取的 SysInternals 进程监视器文件夹
  3. 双击 SysInternals 进程监视器 (procmon.exe) 文件,启动应用。
  4. 如果 UAC 提示,请选择“ ”按钮。
  5. 在“进程监视器筛选器”窗口中,选择标记为 “体系结构”的第一个下拉菜单。
  6. 从下拉菜单中选择 “进程名称 ”。
  7. 在下一个下拉菜单中,验证是否已使用其值进行设置。
  8. 在文本字段中,键入应用 (示例的进程名称:PSFSample.exe) 。 Example of the Process Monitor Filter Windows with App Name
  9. 选择“添加”按钮。
  10. 在“进程监视器筛选器”窗口中,选择标记为 “进程名称”的第一个下拉菜单。
  11. 从下拉菜单中选择 “结果 ”。
  12. 在下一个下拉菜单中,选择它,并从下拉菜单中选择
  13. 在文本字段类型中: SUCCESSExample of the Process Monitor Filter Windows with Result
  14. 选择“添加”按钮。
  15. 选择“确定”按钮。
  16. 启动Windows应用,触发错误,并关闭Windows应用。

查看Windows应用故障日志

捕获Windows应用进程后,需要调查结果,以确定故障是否与工作目录相关。

  1. 查看 SysInternals 进程监视器结果,搜索上表中概述的失败。
  2. 如果结果显示 “找不到名称” 结果,其中详细信息 为“Desired Access: ...” for your specific app targeting a directory of the directory of the “C:\Program Files\WindowsApps\...\” (,如下图) 所示,则你已成功识别与工作目录相关的故障,请使用 PSF 支持 - 文件系统访问 文章,了解如何将 PSF 更正应用到你的应用。 Displays the error message witnessed in the SysInternals Process Monitor for failure to write to directory.

解决方法

Windows应用会将与应用程序相关的特定目录重定向到Windows应用容器文件夹。 如果应用程序在安装过程中创建子文件夹 (C:\Program Files\Vendor\subfolder) ,稍后将调用此子文件夹,则找不到目录,因为它不存在。

若要解决与引用错误工作目录Windows应用相关的问题,必须执行以下四个步骤:

  1. 将Windows应用暂存到本地目录
  2. 创建 Config.json 并注入所需的 PSF 文件
  3. 更新 Windows AppxManifest 文件
  4. 重新打包并签署Windows应用

上述步骤提供了指导,将Windows应用的内容提取到本地暂存目录,将 PSF 修复文件注入到暂存Windows应用目录中,将应用程序Launcher配置为指向 PSF 启动器,然后将 PSF config.json 文件配置为将 PSF 启动器重定向到指定工作目录的应用。

下载并安装所需的工具

此过程将指导你检索和使用以下工具:

  • NuGet客户端工具
  • 包支持框架
  • Windows 10 SDK(最新版本)
  • SysInternals 进程监视器

下面提供了有关下载和安装所需工具的分步指南。

  1. 下载NuGet客户端工具的最新 (非预览版) 版本,并将nuget.exeC:\PSF\nuget保存在文件夹中。

  2. 通过从管理 PowerShell 窗口运行以下命令,使用 Nuget 下载包支持框架:

    Set-Location "C:\PSF"
    .\nuget\nuget.exe install Microsoft.PackageSupportFramework
    
  3. 下载并安装 Windows 10 软件开发Toolkit (Win 10 SDK)

    1. 下载 Win 10 SDK
    2. 运行在上一步中下载的 winsdksetup.exe
    3. 选择“下一步”按钮。
    4. 仅选择以下三项功能进行安装:
      • 适用于桌面应用的 Windows SDK 签名工具
      • 适用于 UWP C++ 应用的 Windows SDK
      • 适用于 UWP 应用的 Windwos SDK 本地化
    5. 选择“安装”按钮。
    6. 选择“确定”按钮。

暂存Windows应用

通过暂存Windows应用,我们将提取/解压缩Windows应用的内容到本地目录。 将Windows应用解压缩到暂存位置后,可以注入 PSF 修复文件以更正任何不需要的体验。

  1. 打开管理 PowerShell 窗口。

  2. 设置面向特定应用文件的以下变量,并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
    
  3. 通过运行以下 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应用Launcher的信息。 如果有多个Windows应用启动器遇到问题,可以使用多个条目更新 config.json 文件。

更新 config.json 文件后,必须将 config.json 文件和支持的 PSF 修复文件移动到 Windows 应用包的根目录中。

  1. 打开Visual Studio Code (VS Code) 或任何其他文本编辑器。

  2. 通过选择VS Code顶部的“文件”菜单,从下拉菜单中选择“新建文件”,创建新文件

  3. 将文件另存为 config.json,方法是选择VS Code窗口顶部的“文件”菜单,从下拉菜单中选择“保存”。 在“另存为”窗口中,导航到Windows应用暂存目录 (C:\PSF\Staging\PSFSampleApp) 并将文件名设置为 config.json。 选择“保存”按钮。

  4. 将以下代码复制到新创建的 config.json 文件。

    {
        "applications": [
            {
                "id": "",
                "executable": "",
                "workingDirectory": ""
            }
        ],
        "processes": [
            {
                "executable": ""
            }
        ]
    }
    
  5. 使用 VS Code 或其他文本编辑器打开位于Windows应用暂存文件夹 (C:\PSF\Staging\PSFSampleApp\AppxManifest.xml) 的 暂存Windows AppxManifest 文件。

    <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. ID 字段中的值复制到 config.json 文件中AppxManifest.xml文件中Package.Applications.Application的应用程序 ID 字段。 Image circling the location of the ID within the AppxManifest file.

  7. 将位于 AppxManifest.xml 文件中Package.Applications.Application“可执行文件”字段的包相对路径复制到 config.json 文件中的“应用程序可执行文件”字段。 Image circling the location of the executable within the AppxManifest file.

  8. 将包相对父路径从位于 AppxManifest.xml 文件中Package.Applications.Application可执行文件字段复制到 config.json 文件中的 Applications WorkingDirectory 字段。 Image circling the location of the working directory within the AppxManifest file.

  9. 可执行文件名称从位于 Package.Applications.ApplicationAppxManifest.xml 文件中的可执行文件字段复制到 config.json 文件中的“进程可执行文件”字段。 Image circling the location of the process executable within the AppxManifest file.

  10. 保存更新后的 config.json 文件。

    {
        "applications": [
            {
            "id": "PSFSample",
            "executable": "VFS/ProgramFilesX64/PS Sample App/PSFSample.exe",
            "workingDirectory": "VFS/ProgramFilesX64/PS Sample App/"
            }
        ],
        "processes": [
            {
            "executable": "PSFSample"
            }
        ]
    }
    
  11. 将基于应用程序可执行体系结构的包支持框架中的以下三个文件复制到暂存Windows应用的根目录。 以下文件位于 .\Microsoft.PackageSupportFramework 中。<Version>\bin

    应用程序 (x64) 应用程序 (x86)
    PSFLauncher64.exe PSFLauncher32.exe
    PSFRuntime64.dll PSFRuntime32.dll
    PSFRunDll64.exe PSFRunDll32.exe

更新 AppxManifest

创建和更新 config.json 文件后,必须为 config.json 中包含的每个Windows应用Launcher更新Windows应用AppxManifest.xml。 AppxManifest 的应用程序现在必须面向与应用程序体系结构关联的PSFLauncher.exe

  1. 打开文件资源管理器,然后导航到分阶段 MSIX 应用文件夹 (C:\PSF\Staging\PSFSampleApp) 。

  2. 右键单击 AppxManifest.xml,然后从下拉菜单中选择“ 使用代码打开 ”, ((可选)可以打开另一个文本编辑器) 。

  3. 使用以下信息更新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