UWP应用遇System.UnauthorizedAccessException:如何获取文件夹读写权限?
这个问题在UWP开发里太常见了——毕竟UWP默认跑在沙箱环境里,直接用传统.NET的DirectoryInfo这类IO API去碰桌面、文档这类系统路径,肯定会被权限拦截。下面给你几个靠谱的解决方案,按需选择:
方案1:用文件/文件夹选取器(最合规,推荐优先用)
UWP的安全模型要求用户主动授权访问非沙箱内的文件/文件夹,所以用系统自带的选取器是最稳妥的方式,不需要额外配置权限,用户点选后应用就能访问目标路径。
示例代码:
// 创建文件夹选取器 var folderPicker = new Windows.Storage.Pickers.FolderPicker(); folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop; folderPicker.FileTypeFilter.Add("*"); // 允许选择任意类型的文件夹 // 弹出选取器,等待用户选择 StorageFolder selectedFolder = await folderPicker.PickSingleFolderAsync(); if (selectedFolder != null) { // 这里可以安全地访问选中的文件夹,比如获取子文件夹 var subFolders = await selectedFolder.GetFoldersAsync(); // 或者用StorageFolder的其他方法操作文件/文件夹 }
注意:这种方式下,应用只会获得用户选中的那个文件夹的访问权限,而且权限会被系统记住,下次启动不用再选。
方案2:声明已知文件夹权限(适合需要自动访问桌面/文档等路径的场景)
如果你的应用需要无需用户手动选取就能访问桌面、文档这类已知文件夹,可以在应用清单里声明对应的权限,再结合UWP的KnownFolders API来访问。
步骤1:修改Package.appxmanifest
打开应用的Package.appxmanifest文件,切换到"功能"标签,勾选对应的已知文件夹权限,比如:
- 文档库
- 图片库
- 视频库
- 音乐库
- (Windows 10 1809及以上)文件系统(这个是broadFileSystemAccess能力,能访问更多路径)
如果是手动编辑XML的话,添加以下内容到<Capabilities>节点:
<Capabilities> <Capability Name="internetClient" /> <!-- 访问桌面、文档等需要添加下面的 --> <uap:Capability Name="documentsLibrary" /> <uap:Capability Name="picturesLibrary" /> <!-- Windows 10 1809+ 可用的全文件系统访问 --> <uap:Capability Name="broadFileSystemAccess" /> </Capabilities>
步骤2:用KnownFolders访问目标路径
声明权限后,就可以用UWP的API来访问对应的文件夹,不要用System.IO的DirectoryInfo/FileInfo,必须用StorageFolder/StorageFile:
// 访问桌面文件夹 StorageFolder desktopFolder = KnownFolders.Desktop; // 获取子文件夹 var subFolders = await desktopFolder.GetFoldersAsync(); // 如果你声明了broadFileSystemAccess,还能访问更多路径,比如指定的文件夹 // 注意:broadFileSystemAccess需要用户在系统设置里给权限:设置>隐私和安全性>文件系统>允许应用访问你的文件系统
方案3:开启开发者模式的特殊权限(仅用于调试)
如果只是本地调试需要快速访问任意路径,可以开启UWP的开发者模式权限:
- 打开Windows设置 -> 隐私和安全性 -> 开发者选项
- 找到"文件系统",开启"允许开发人员访问文件系统"
不过这个方法只适合调试,发布到商店的应用不能依赖这个,因为普通用户不会开启开发者模式。
关键提醒:别再用System.IO的API!
你原来的代码用DirectoryInfo属于传统.NET IO API,这类API不受UWP沙箱权限的管控,哪怕你拿到了权限,用它们访问还是会报UnauthorizedAccessException。必须替换成UWP原生的StorageFolder、StorageFile和对应的异步方法(比如GetFoldersAsync()、GetFilesAsync())。
内容的提问来源于stack exchange,提问作者Mark Velenur

