本文介绍如何使用包支持框架(PSF)解决文件系统写入权限错误。
Windows 应用将特定应用程序相关目录重定向到 C:\Program Files\WindowsApps
该文件夹。 如果应用程序尝试写入 Windows 应用容器,将触发错误,并且写入失败。 你可以对 Windows 应用包进行增强,以解决此问题。
调查
首先,确定失败以及应用请求的目录路径。
捕获 Windows 应用错误
筛选结果是可选的,但更易于查看与应用程序相关的故障。 若要筛选结果,请创建两个筛选规则。 第一个筛选器包括应用程序进程名称,第二个筛选器包含未成功的任何结果。
下载 SysInternals 进程监视器 并将其提取到 C:\PSF\ProcessMonitor 目录。
打开 Windows 资源管理器并导航到提取的 SysInternals ProcessMonitor 文件夹。
选择 SysInternals 进程监视器 procmon.exe 文件以启动应用。
如果 UAC 提示,请选择“ 是”。
在 “进程监视器筛选器 ”窗口中,从第一个字段的下拉菜单中选择 “进程名称 ”。
验证 is 是否出现在下一个字段中。
在下一个字段中,输入应用的进程名称,例如 PSFSample.exe。
选择 “添加”。
在 “进程监视器筛选器 ”窗口中,从第一个字段的下拉菜单中选择 “结果 ”。
在下一个字段中,从下拉菜单选择“不是”。
在文本字段中,输入 SUCCESS。
依次选择“添加”、“确定” 。
启动 Windows 应用,触发错误,然后关闭 Windows 应用。
查看 Windows 应用失败日志
捕获 Windows 应用进程后,调查结果以确定失败是否与工作目录相关。
查看 SysInternals 进程监视器的故障结果。 如果结果包括 访问被拒绝,且 具有‘预期访问:通用写入’详细信息,对于面向 C:\Program Files\WindowsApps\...\ 的应用程序,您已发现与工作目录相关的写入权限失败问题。
如果确定此错误,请对应用应用以下 PSF 更正。
决议
若要解决 Windows 应用无法写入 Windows 应用容器的问题,请执行以下步骤:
- 将 Windows 应用的内容提取到 本地暂存目录。
- 创建config.json并将 PSF 修复文件注入到暂存的 Windows 应用目录中。
- 将应用程序启动器配置为指向 PSF 启动器,并将 PSF config.json 文件配置为重定向 PSF 启动器,并指定工作目录。
- 更新 Windows 应用 AppxManifest 文件。
- 重新打包并签署 Windows 应用。
下载并安装所需的工具
此过程需要以下工具:
- NuGet 客户端工具
- 包支持框架 (PSF)
- Windows 10 软件开发工具包(Win 10 SDK),最新版本
- SysInternals 进程监视器
下载并安装 NuGet 和 PSF:
下载 NuGet 客户端工具的最新非预览版,并在 C:\PSF\nuget 中保存 nuget.exe。
通过从管理 PowerShell 窗口运行以下命令,下载并安装 NuGet 包支持框架:
Set-Location "C:\PSF" .\nuget\nuget.exe install Microsoft.PackageSupportFramework
下载并安装 Windows 10 SDK:
- 下载 Win 10 SDK。
- 运行 winsdksetup.exe 。
- 选择 “下一步”。
- 仅选择以下三个功能:
- 适用于桌面应用的 Windows SDK 签名工具
- 适用于 UWP C++ 应用的 Windows SDK
- 用于 UWP 应用本地化的 Windwos SDK
- 选择 “安装”,然后选择“ 确定”。
暂存 Windows 应用
暂存 Windows 应用会将应用的内容提取并解压缩到本地目录。 将 Windows 应用解压缩到暂存位置后,可以注入 PSF 修复文件以更正任何不需要的体验。
在管理 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
通过运行以下 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 应用包的根目录中。
打开 Visual Studio Code 或其他文本编辑器。
在 Windows 应用暂存目录 C:\PSF\Staging\PSFSampleApp 中创建名为 config.json 的新文件。
将以下代码复制到新创建的 config.json 文件。
{ "applications": [ { "id": "", "executable": "" } ], "processes": [ { "executable": "", "fixups": [ { "dll": "", "config": { "redirectedPaths": { "packageRelative": [ { "base": "", "patterns": [ "" ] } ] } } } ] } ] }
在 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>
在 config.json 文件中进行以下更改:
将
applications.id
值设置为与Applications.Application.ID
文件中字段中的值相同。将
applications.executable
值设置为指向位于Applications.Application.Executable
文件的 字段中应用程序的相对路径。设置
applications.workingdirectory
值以定位Applications.Application.Executable
文件中字段的相对文件夹路径。在
process.executable
文件的Applications.Application.Executable
字段中,将 值设置为仅目标文件名,不包括路径和扩展名。将
processes.fixups.dll
值设置为面向特定于体系结构的FileRedirectionFixup.dll
。 如果更正适用于 x64 体系结构,请将该值FileRedirectionFixup64.dll
设置为 。 如果体系结构为 x86 或未知,请将该值设置为FileRedirectionFixup86.dll
。将
processes.fixups.config.redirectedPaths.packageRelative.base
值设置为Applications.Application.Executable
文件的字段中的包相对文件夹路径。设置值
processes.fixups.config.redirectedPaths.packageRelative.patterns
以匹配应用程序创建的文件类型。 如果使用.*\\.log
,PSF 将重定向processes.fixups.config.redirectedPaths.packageRelative.base
目录和子目录中的所有日志文件写入。
保存更新 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" ] } ] } } } ] } ] }
将以下文件从应用程序可执行体系结构的包支持框架复制到暂存 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 应用启动器的 AppxManifest.xml 文件。
AppxManifest.xmlApplications
现在必须面向与应用程序体系结构关联的 PSFLauncher.exe。
- 在暂存的 MSIX 应用文件夹中打开 AppxManifest.xmlC:\PSF\Staging\PSFSampleApp。
- 使用以下代码更新 AppxManifest.xml :
<Package ...> ... <Applications> <Application Id="PSFSample" Executable="PSFLauncher32.exe" EntryPoint="Windows.FullTrustApplication"> ... </Application> </Applications> </Package>
重新打包应用程序
应用所有更正后,将 Windows 应用重新打包到 MSIX 中,并使用代码签名证书对其进行签名。
打开管理 PowerShell 窗口。
设置以下变量:
$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
通过运行以下 PowerShell cmdlet 从暂存文件夹重新打包 Windows 应用:
Set-Location "${env:ProgramFiles(x86)}\Windows Kits\10\Bin\$Win10SDKVersion\$OSArchitecture" .\makeappx.exe pack /p "$AppPath" /d "$StagingFolder"
通过运行以下 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