Windows 2004 和 20H2 上的 WPF 桌面桥 ApplicationData.GetPublisherCacheFolder UnauthorizedAccessException

问题描述

我有一个 WPF 应用程序,其中包含桌面桥包项目。 WPF 项目安装了 nuget Microsoft.Windows.SDK.Contracts。 在 package.appxmanifest 中,我添加了适当的权限:

<Extensions>
  <Extension Category="windows.publisherCacheFolders">
    <PublisherCacheFolders>
      <Folder Name="SomeFolder" />
    </PublisherCacheFolders>
  </Extension>
</Extensions>

我想在属于一个发布者的多个 WPF 和 UWP 应用程序之间共享一些信息。 我调用 Windows 运行时 API:

var folder = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("SomeFolder");
var file = await folder.CreateFileAsync("SomeFile",CreationCollisionoption.OpenIfExists);

我得到 System.UnauthorizedAccessException: '访问被拒绝。 无法访问指定的文件文件夹 (C:\Users\AppData\Local\Publishers\5w92pj7ar334m\SomeFolder\SomeFile)。确认该项目未标记系统或隐藏文件属性。'

在 System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 在 GetPublisherFolderWPF.MainWindow.d__1.MoveNext()

文件夹 5w92pj7ar334m 和 SomeFolder 是在部署这个应用程序后创建的,并且文件 SomeFile 也创建了零大小。

这发生在 Windows 2004 和 20H2 上。在较早版本的 Windows 10 上,此代码运行良好。

Sample project

解决方法

如果要获取生成的文件并写入,建议使用System.IO命名空间下的File.Open方法获取文件流,不会造成权限问题。请参考以下代码。

private async void Button_Click(object sender,RoutedEventArgs e)
        {
            var folder = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("SomeFolder");
            try { stream = File.Open(folder.Path + "/SomeFile.txt",FileMode.Open); }
            catch
            {
                file = await folder.CreateFileAsync("SomeFile.txt",CreationCollisionOption.GenerateUniqueName);
                stream = File.Open(folder.Path + "/SomeFile.txt",FileMode.Open);
            }
          
            finally
            {
                var buffer = Encoding.UTF8.GetBytes("SomeContent");
                await stream.WriteAsync(buffer,buffer.Length);
                stream.Dispose();
            }

        }