并非总是可以在“干净”的 Windows 8.1 上捕获 WoW64 上的 SEH

Posted

技术标签:

【中文标题】并非总是可以在“干净”的 Windows 8.1 上捕获 WoW64 上的 SEH【英文标题】:Not always can catch SEH on WoW64 on "clean" Windows 8.1 【发布时间】:2014-02-18 09:38:17 【问题描述】:

我有用 VS2008 编译的 Win32 MFC 应用程序。该应用程序具有 TreeConrtol。有一个 TVN_ITEMCHANGING 处理程序,在处理程序内我强制重新绘制更改的树项。

这是带有 SEH 处理程序和直接 WinAPI 调用而不是 MFC 包装器的代码(这不会影响问题):

void CMainDlg::OnTvnItemChangingMainTree(NMHDR *pNMHDR, LRESULT *pResult)

    NMTVITEMCHANGE *pNMTVItemChange = reinterpret_cast(pNMHDR);

    HWND hTreeCtrl = _ctrlTree.GetSafeHwnd();
    RECT rect;
    __try
    
        *(HTREEITEM*) &rect = hItem; 
        if ((BOOL) ::SendMessage(hTreeCtrl, TVM_GETITEMRECT, 
                (WPARAM) FALSE, (LPARAM) &rect))
        
            ::InvalidateRect(hTreeCtrl, &rect, TRUE); 
        
    
    __except(EXCEPTION_EXECUTE_HANDLER)
    
        ::MessageBox(NULL, L"SEH exception is Here", L"__except Block", MB_OK);
    
    *pResult = 0;
   

如果我在树控件中选择一个项目(以编程方式或通过鼠标单击),那么在从树控件中删除所有项目后(通过使用 DeleteAllItems 或一个接一个)我将获得 TVN_ITEMCHANGING 的项目已经不存在,所以上面的代码在调用 ::SendMessage(hTreeCtrl, TVM_GETITEMRECT, ...) 时会引发结构化异常。

没关系,但是... __except 块永远不会在某些 Windows 8.1 Pro x64 上执行(可能在其他 Windows 版本上)。

我的工作机器是从 Windows 8 更新的英文 Windows 8.1 Pro x64(内部版本 9600)。在那台机器上一切正常(处理程序捕获异常并显示 MessageBox)。但是,在从 MSDN 下载的干净的英文 Windows 8.1 Pro x64(内部版本 9600)上,__except 块未被调用并且应用程序崩溃。故障模块名称:COMCTL32.dll

我在两台计算机上运行相同的 .exe 文件。您认为为什么会发生这种情况?

这是一个工作示例。我用 /EHsc 编译它,然后用 /EHa 编译它(真正的项目是用 /EHa 编译并使用 try/catch)。

示例中的代码与上面的函数不同:我添加了使用 try/catch 和 _try/_except 的选项。

使用 /EHa 我可以在我的工作机器上使用 try/catch 或 _try/_except 捕获异常,使用 /EHsc 使用 _try/_except。但是这些组合都不适用于另一台机器(使用干净的 Win8.1):它不会捕获异常。

演示项目(使用 Visual Studio 2008 Professional SP1 + MFC 编译):here。

PS:通过在 SendMessage() 调用中添加 if 条件暂时解决了问题,但这里我想调查一下异常处理的问题。

提前感谢您的 cmets。

【问题讨论】:

这是一种可怕的做法。吞下第一个程序后,您将无法再推理程序的状态。 【参考方案1】:

您无法控制 RaiseException(或等效项)和 __try/__except 之间的所有帧:中间有 SendMessage() 调用。

Raymond Chen 解释得最好:When you transfer control across stack frames, all the frames in between need to be in on the joke

【讨论】:

感谢链接,它非常具有认知性,并解释了当您捕获异常时可能发生的情况,但不控制中间的所有帧,但它没有解释原因异常可能会在一台机器上被捕获,而可能不会在另一台具有相同 Windows 版本和构建的机器上被捕获

以上是关于并非总是可以在“干净”的 Windows 8.1 上捕获 WoW64 上的 SEH的主要内容,如果未能解决你的问题,请参考以下文章

打开或关闭windows功能。总是提示"出现错误.并非所有的功能被成功更改"

如何在Windows 8.1 / 10上可靠地窃取/重新获得MFC /桌面应用程序的焦点?

当我使用后台任务时,Windows phone 8.1 应用程序发布失败

Win32 应用程序是不是也可以在 Windows 7 和 Windows 8/8.1 上运行?

Windows 8.1 和 Windows 10 应用程序问题

在 Windows 8.1 上运行 Windows 10 通用应用