UWP NeighbourFilesQuery偶发System.OverflowException问题求助
为什么API行为会不一致?
这个问题的核心在于 NeighboringFilesQuery 的过滤逻辑完全依赖系统注册的文件类型与内容分类。UWP系统默认只会把被识别为「可播放媒体」的文件纳入查询结果——而像 .flv、.rm 这类格式,要么系统默认没有将其归类为媒体文件,要么你的应用没有正确注册这些文件类型的关联声明,导致API在查询时直接排除了被点击的目标文件。
当目标文件不在 NeighboringFilesQuery 的结果集中时,FindStartIndexAsync 会返回一个无效的极大值(通常是 UInt64.MaxValue),这时候直接将其转换为 int32 就会触发 System.OverflowException,因为这个值远超 int 的范围(-231到231-1)。
解决步骤
1. 确保应用正确注册目标文件类型
首先在你的 Package.appxmanifest 中添加 .flv、.rm 等格式的文件关联声明,告诉系统这些文件是你的应用可以处理的媒体类型。示例配置如下(在 Extensions 节点下添加):
<Extensions> <uap:Extension Category="windows.fileTypeAssociation"> <uap:FileTypeAssociation Name="customvideo"> <uap:DisplayName>Custom Video Formats</uap:DisplayName> <uap:SupportedFileTypes> <uap:FileType>.flv</uap:FileType> <uap:FileType>.rm</uap:FileType> </uap:SupportedFileTypes> <uap:ContentTypes> <uap:ContentType>video/x-flv</uap:ContentType> <uap:ContentType>application/vnd.rn-realmedia</uap:ContentType> </uap:ContentTypes> </uap:FileTypeAssociation> </uap:Extension> </Extensions>
完成注册后,系统会将这些格式识别为你的应用支持的媒体文件,NeighboringFilesQuery 就会将它们纳入结果集。
2. 添加无效索引的判断逻辑
即使完成了文件注册,也建议对 FindStartIndexAsync 的结果做有效性检查,避免极端场景下的异常。修改你的代码如下:
var file = args.Files[0]; StorageFileQueryResult neighboringFilesQuery = args.NeighboringFilesQuery; var startingIndexUnit = await neighboringFilesQuery.FindStartIndexAsync(file); int startingIndex; // 检查返回值是否为无效索引(UInt64.MaxValue代表未找到) if (startingIndexUnit == UInt64.MaxValue) { // 手动查询父目录下的所有支持文件 var parentFolder = await file.GetParentAsync(); if (parentFolder != null) { // 定义你的应用支持的所有媒体扩展名 var supportedExtensions = new[] { ".mp4", ".flv", ".rm", ".avi", ".mkv", ".mov" }; var queryOptions = new QueryOptions(CommonFileQuery.DefaultQuery, supportedExtensions); var fileQuery = parentFolder.CreateFileQueryWithOptions(queryOptions); var allFiles = await fileQuery.GetFilesAsync(); // 找到当前文件在列表中的索引 startingIndex = allFiles.IndexOf(file); // 兜底:如果找不到(理论上不会发生),默认从0开始 startingIndex = startingIndex == -1 ? 0 : startingIndex; } else { // 无法获取父目录,默认从0开始 startingIndex = 0; } } else { // 正常转换为int startingIndex = Convert.ToInt32(startingIndexUnit); } // 后续处理播放列表逻辑
3. (可选)完全替代NeighboringFilesQuery
如果不想依赖系统的查询逻辑,也可以直接绕过 NeighboringFilesQuery,手动遍历父目录获取所有支持的媒体文件,这样行为完全可控:
var file = args.Files[0]; var parentFolder = await file.GetParentAsync(); List<StorageFile> playlist = new List<StorageFile>(); if (parentFolder != null) { var supportedExtensions = new[] { ".mp4", ".flv", ".rm", ".avi", ".mkv" }; var queryOptions = new QueryOptions(CommonFileQuery.DefaultQuery, supportedExtensions); var fileQuery = parentFolder.CreateFileQueryWithOptions(queryOptions); playlist = (await fileQuery.GetFilesAsync()).ToList(); } // 确保当前文件在列表中(如果不在就添加到开头) if (!playlist.Contains(file)) { playlist.Insert(0, file); } // 获取当前文件的索引 int startingIndex = playlist.IndexOf(file);
这种方式完全不受系统文件类型识别的影响,能保证所有你支持的文件都被纳入播放列表。
内容的提问来源于stack exchange,提问作者Muhammad Touseef

