是否可以从.net app禁用c ++ assert

时间:2010-11-10 13:30:46

标签: c# c++

我有以下问题: 我使用来自我的WPF应用程序的c ++库,该库在一些非常罕见的情况下抛出一个断言。它显示了一个很好的对话框,其中包含c ++文件名,行号和断言表达式。所以问题是:我可以在c ++库中禁用断言,假设我没有源代码。我真正需要的是“捕获”这个断言并记录下来。

感谢。

3 个答案:

答案 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年的库完成的。