VS2022中WPF OpenFileDialog调试模式报错,无调试模式正常
问题详情
在WPF窗体中通过按钮触发OpenFileDialog,代码如下:
<Grid> <Button Name="btn_rss_AddImage" Grid.Row="0" Grid.Column="1" Click="GetImageAttachment" Margin="20, 0">Choose Image</Button> </Grid>
private void GetImageAttachment(object sender, RoutedEventArgs e) { OpenFileDialog dlg = new(); dlg.DefaultExt = ".xml"; if (dlg.ShowDialog() == true) { string filename = dlg.FileName; } }
调试模式运行时,输出窗口出现数百条重复异常,OpenFileDialog响应卡顿,异常从加载C:\Program Files\Norton\Suite\ashShell.dll后开始出现,示例异常:
(Win32): Loaded 'C:\Program Files\Norton\Suite\ashShell.dll'.
Exception thrown at 0x00007FFE2E9EB699 in WPF_ShipDataBase.exe: Microsoft C++ exception: asw::registry::exceptions::key_not_exists at memory location 0x0000008323D7A380.
Exception thrown at 0x00007FFE2E9EB699 in WPF_ShipDataBase.exe: Microsoft C++ exception: asw::storage::exit_callback_not_found_exception at memory location 0x0000008323D7C040.
但无调试模式启动时,OpenFileDialog可正常工作且无错误。
原因分析
这是Norton安全软件的shell扩展组件(ashShell.dll)与Visual Studio调试器的异常捕获机制冲突导致的:
- ashShell.dll作为系统shell扩展,会注入到所有打开文件对话框的进程中,包括你的WPF调试进程
- 该组件内部抛出的非致命C++异常,在调试模式下被Visual Studio的调试器捕获并输出,大量重复异常导致对话框响应卡顿
- 无调试模式下,系统默认忽略这类非致命异常,所以对话框正常工作
解决思路
1. 调整Visual Studio调试异常捕获设置
- 打开Visual Studio的调试 → Windows → 异常设置(快捷键:Ctrl+Alt+E)
- 在弹出窗口中,找到C++ Exceptions,取消勾选特定异常(
asw::registry::exceptions::key_not_exists、asw::storage::exit_callback_not_found_exception);或临时取消勾选整个C++ Exceptions的启用状态(注意调试其他代码时需恢复,避免遗漏重要异常) - 开启仅我的代码(路径:Options → Debugging → General → Enable Just My Code),让调试器只监控你编写的代码抛出的异常,忽略第三方组件的异常
2. 临时禁用Norton的shell扩展
- 打开Norton安全软件设置,找到系统集成类选项,暂时关闭文件对话框相关的扩展功能
- 或使用命令卸载该shell扩展:
regsvr32 /u "C:\Program Files\Norton\Suite\ashShell.dll",调试完成后再用regsvr32 "C:\Program Files\Norton\Suite\ashShell.dll"恢复
3. 替代方案:调用Win32 API绕过WPF封装的对话框
如果上述方法无效,可以直接使用Win32原生的文件选择函数,避免加载第三方shell扩展:
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool GetOpenFileName([In, Out] OPENFILENAME lpofn); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private struct OPENFILENAME { public int lStructSize; public IntPtr hwndOwner; public IntPtr hInstance; public string lpstrFilter; public string lpstrCustomFilter; public int nMaxCustFilter; public int nFilterIndex; public string lpstrFile; public int nMaxFile; public string lpstrFileTitle; public int nMaxFileTitle; public string lpstrInitialDir; public string lpstrTitle; public int Flags; public ushort nFileOffset; public ushort nFileExtension; public string lpstrDefExt; public IntPtr lCustData; public IntPtr lpfnHook; public string lpTemplateName; public IntPtr pvReserved; public int dwReserved; public int FlagsEx; } private void GetImageAttachment(object sender, RoutedEventArgs e) { OPENFILENAME ofn = new(); ofn.lStructSize = Marshal.SizeOf(ofn); ofn.lpstrFilter = "XML Files (*.xml)\0*.xml\0All Files (*.*)\0*.*\0"; ofn.lpstrFile = new string(new char[256]); ofn.nMaxFile = ofn.lpstrFile.Length; ofn.lpstrDefExt = "xml"; ofn.Flags = 0x00080000 | 0x00001000; // OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST if (GetOpenFileName(ref ofn)) { string filename = ofn.lpstrFile; } }
内容的提问来源于stack exchange,提问作者Fred F

