我有以下问题: 我使用来自我的WPF应用程序的c ++库,该库在一些非常罕见的情况下抛出一个断言。它显示了一个很好的对话框,其中包含c ++文件名,行号和断言表达式。所以问题是:我可以在c ++库中禁用断言,假设我没有源代码。我真正需要的是“捕获”这个断言并记录下来。
感谢。
答案 0 :(得分:4)
一种方法是创建一个每隔一段时间执行EnumWindows
的线程,并检测是否弹出一个断言窗口,然后它可以捕获该消息并单击忽略按钮。这仍然会导致窗口显示一段时间(取决于EnumWindows
之间的间隔,但我假设您的客户不会获得调试DLL,因此它无关紧要。
另一个选择是调用_CrtSetReportMode(_CRT_ASSERT, 0)
来禁止断言完全显示。
如果你想从.NET中引用它,请注意_CRT_ASSERT
等于2。
答案 1 :(得分:1)
根据您的汇编程序技能以及是否故意采取措施来阻止此类内容,通常可以修改二进制代码以防止显示此类消息。
然而,断言解雇往往是一些更为壮观的崩溃或其他不当行为的前兆,所以只是停止消息框可能不会让你更进一步。当然,有些断言是错误的,所以这可能就是你所需要的。
如果我不得不修改这个DLL,我会用IDA对它进行反汇编并制作一个补丁。隐藏断言可能相当容易,记录起来要困难得多。
答案 2 :(得分:0)
我最近不得不修复一些依赖于DLL的旧代码,这些代码有时会弹出一个断言消息。我尝试了以上所有建议,而我唯一能做的就是点击忽略按钮。上面的用户建议在一个单独的线程上运行EnumWindows - 我改为使用FindWindow。
这是找到Assert弹出消息的函数,在其中找到Ignore按钮,然后单击它。它继续循环,每次检查一个全局变量(丑陋但快速):
void CloseAssertBox (void *param) {
HWND window, button;
Sleep (200); //wait 200 milliseconds
while (!finishThread) { //see if we can stop checking
if ((window = FindWindow (NULL, L"Microsoft Visual C++ Runtime Library"))
&& (button = FindWindowEx (window, NULL, L"Button", L"&Ignore")))
SendMessage (button, BM_CLICK, 0, 0); //click the button
Sleep (50); //then check every 50 milliseconds
}
}
Assert框的标题可能不同。如果您的忽略按钮的引用方式不同,您可以使用EnumChildWindows获取每个子控件的名称,包括按钮。
在弹出断言的代码位之前,我启动一个调用上面函数的新线程。
finishThread = 0; //this is set to 1 when the thread should finish
_beginthread (CloseAssertBox, 0, NULL); //begin the thread
在完成危险的断言代码后,我设置了:
finishThread = 1; //done threaded stuff
这样线程将在下一次循环时关闭。这可能是更好的方法。
我必须包含这些库才能使其正常工作:
#include <process.h> //for multithreading
#include <WinBase.h> //for Sleep function
int finishThread; //to tell the thread when encoding has finished
这一切都是在Visual Studio 2010中使用2006年的库完成的。