在混合模式下使用本机C++、托管C++/CLI和C#解决方案进行调试

33

我正在进行一个多线程项目,启动项目设置为运行我的用户界面的c#项目。然后有一系列底层的c++本地项目,通过托管的C++/CLI项目与C#相连接。我已经在c#启动项目中启用了“启用非托管调试”,当我尝试调试本地代码时,我能够命中设置的断点。然而,在我再次尝试运行并尝试再次命中断点之后,它就会挂起。例如,如果我想在每次迭代中命中循环内部的断点,在第二次迭代后程序会挂起,并且我必须强制退出。我使用的是Visual Studio 2010。以这种速率进行调试开始变得不太有用了,有没有什么办法可以避免这个问题?


2
使用多个调试器实例。一个用于托管代码,另一个用于非托管代码。当然,这意味着您将不得不根据情况附加和分离。当然,与其整个应用程序调试不如进行强大的单元测试和集成测试。 - Ritch Melton
1
@Ritch:多个调试器实例的建议听起来非常有趣。在我看来,值得给出一个全面的答案。 - Martin Ba
1
@Ritch:我认为经常失败的单元测试和特别是集成测试会导致你使用调试器来找出到底出了什么问题! - Martin Ba
@Martin 这是我过去的做法。这是一个非常大的项目,但是很容易确定错误发生在哪一方。 - Ritch Melton
4个回答

42

当我想要同时调试本地代码和 C++/CLI 时,我会执行以下步骤:

  1. 在 C# 应用程序中,在项目属性的“生成”选项卡中勾选“允许不安全代码”,在“调试”选项卡中勾选“启用非托管代码调试”。
  2. 对于 C++/CLI 的 DLL 项目,在属性的“调试”选项卡中,将“调试器类型”设置为“混合”。

2
对我来说,“允许不安全代码”是关键。虽然我已将“启用非托管代码”设置,但直到我加入“允许不安全代码”,它才不再崩溃。 - David Sacks
2
我有一个C# EXE(用于UI),其中包含本地DLL中的遗留代码和我创建的“shim” C++ CLI DLL,以桥接两者。我在本地代码中设置了断点,但调试器没有停止,即使设置了“启用非托管代码”。我为C#项目“允许不安全代码”,并在我的C++ CLI DLL和本地DLL(代码在我的解决方案中)中将“调试器类型”设置为“混合”,然后我就可以在托管和本地代码中停止断点了!太好了! - rich p

8
我们在调试复杂的混合代码应用程序时遇到了问题,并发现Visual Studio在这些情况下并不可靠。我的建议是:
  • 如果您正在尝试调试本地代码,请尝试使用本地项目作为调试器启动应用程序。在项目设置中,“调试”选项卡中将“调试器类型”设置为“混合”,对我们有时有所帮助(本地项目可以是DLL,例如,在项目设置中将主要Exe设置为调试目标);

  • 使用WinDbg,它可以更可靠地调试托管/非托管混合代码应用程序;


2

当我尝试从托管代码进入非托管代码时,遇到了同样的问题,因此我删除了托管端上的所有断点,并执行以下操作:

1)通过文件->打开->文件(例如我的source.cpp)打开您的非托管源文件

2)在那里设置断点

3)启动托管代码调试(播放按钮)

它应该直接中断到您的非托管代码...至少对我有效...


2

好的,这里是我如何解决它的方法:

简短回答:

  1. 为你的两个项目设置Configuration_Properties->Debugging->Debugger_type: Mixed(.NET Framework)。

    a. 纯本地项目(非托管C++ exe从托管C++ CLR dll中消耗导出函数)。

    b. C++/CLI - CLR 项目(托管C++ dll通过引用(C# dll的引用已添加到托管C++ CLR 项目的引用列表中)从纯托管的C# .NET dll导出函数)- 该项目作为无管理代码和托管代码之间的接口。

  2. 为充当接口的托管C++/CLI - CLR 项目设置Configuration_Properties->Advanced->C++/CLI_Properties->Common_Language_Runtime_Support:Common Language Runtime Support (/clr)和.NET_Target_Framework_Version:x.x.x(与托管的C#项目目标框架中指定的版本号相同)。

详细回答:

我正在构建一个插件DLL(C++ Native DLL),它应在纯本地环境(C++ Native)下运行,使用MFC / Win32 API集。首先,我尝试使用Win32Api UI元素,例如窗口、线程等,但设计UI变得很困难,因为VS2019不会给我提供设计编辑器,除非我将项目声明为MFC并带入不需要的MFC服务。

为了简化我的UI开发:

我创建了一个C# dll(托管dLL - 标准类库.NET Core 项目),使用“Windows Forms”,针对.NET框架4.7.2。

然后,我创建了另一个C++/CLI - CLR dll(托管dLL - CLR 项目,它使用未管理的C++代码,但在托管环境clr.dll中运行)。该dll作为接口,使用extern "C" __declspec(dllexport) 将托管C#代码中的函数包装在C样式的包装函数中,公开了这些函数。

主/启动项目是纯本地C ++(exe)无管理应用程序,它消耗从C++ / CLI - CLR 托管接口项目导出的函数,该接口项目内部公开了UI元素。

除非我手动加载托管CLR C++ dll 的.pdb,并将起始未管理C++ 应用程序的调试器类型强制设置为Mixed(.NET Framework),否则无法进行调试。


1
这对我有用。谢谢,mahee96。使用“混合”而不是“自动”会有所不同。 - diwatu
@Gisway 很高兴它对你有帮助! - mahee96

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接