并非总是可以在“干净”的 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 上运行?