MAUI管理员权限下多文件选择器改造异常求助
解决MAUI管理员权限下多文件选择器的异常问题
问题核心分析
调用dialog.GetResults(out IShellItemArray results)时抛出“值不在预期范围内”异常,主要由筛选器配置错误、COM对象未正确释放、对话框状态异常这几类原因导致。
具体修复步骤
1. 修复筛选器配置逻辑
原代码对typeFilters的处理不符合COMDLG_FILTERSPEC的要求,该结构体需要显示名称和筛选模式两个参数,仅传单个值会导致对话框筛选器配置异常,进而影响结果获取。
修改Helper.cs中ShowMulti方法的筛选器处理部分:
if (typeFilters != null) { var filterSpecs = new List<COMDLG_FILTERSPEC>(); // 为每个筛选模式创建对应显示规则(示例用筛选模式作为名称,可按需修改) foreach (var filter in typeFilters) { filterSpecs.Add(new COMDLG_FILTERSPEC(filter, filter)); } // 可选:添加"所有文件"选项 filterSpecs.Insert(0, new COMDLG_FILTERSPEC("所有文件", "*.*")); dialog.SetFileTypes((uint)filterSpecs.Count, filterSpecs.ToArray()); }
2. 正确释放COM对象
未释放IShellItemArray和IShellItem会导致COM资源泄漏,可能引发异常。在获取结果后添加释放逻辑:
if (dialog.Show(windowHandle) != 0) return new(); dialog.GetResults(out IShellItemArray results); List<string> files = new(); try { results.GetCount(out var count); for (uint i = 0; i < count; i++) { results.GetItemAt(i, out var result); try { result.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out var path); files.Add(path); } finally { // 释放单个IShellItem对象 Marshal.ReleaseComObject(result); } } } finally { // 释放IShellItemArray对象 Marshal.ReleaseComObject(results); } return files;
3. 验证窗口句柄的正确性
确保传入的windowHandle是MAUI窗口的有效句柄,Windows平台下可通过以下方式获取:
// 在MAUI页面中获取窗口句柄 var window = Application.Current.Windows.First(); var platformWindow = window.Handler.PlatformView as Microsoft.UI.Xaml.Window; IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(platformWindow);
4. 检查对话框选项冲突
当前使用的FOS_ALLOWMULTISELECT | FOS.FOS_FORCEFILESYSTEM是正确的多文件选择配置,无选项冲突,无需修改。
完整修改后的Helper.cs ShowMulti方法
internal static List<string> ShowMulti(nint windowHandle, FOS fos, List<string>? typeFilters = null) { var dialog = new FileOpenDialog(); try { dialog.SetOptions(fos); if (typeFilters != null) { var filterSpecs = new List<COMDLG_FILTERSPEC>(); foreach (var filter in typeFilters) { filterSpecs.Add(new COMDLG_FILTERSPEC(filter, filter)); } filterSpecs.Insert(0, new COMDLG_FILTERSPEC("所有文件", "*.*")); dialog.SetFileTypes((uint)filterSpecs.Count, filterSpecs.ToArray()); } if (dialog.Show(windowHandle) != 0) return new(); dialog.GetResults(out IShellItemArray results); List<string> files = new(); try { results.GetCount(out var count); for (uint i = 0; i < count; i++) { results.GetItemAt(i, out var result); try { result.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out var path); files.Add(path); } finally { Marshal.ReleaseComObject(result); } } } finally { Marshal.ReleaseComObject(results); } return files; } catch (Exception ex) { // 可选:添加异常日志记录 return new(); } finally { #pragma warning disable CA1416 Marshal.ReleaseComObject(dialog); #pragma warning restore CA1416 } }
内容的提问来源于stack exchange,提问作者Mercury
相关产品推荐
相关产品推荐

