如何调试从外部应用程序调用的类库?

Posted

技术标签:

【中文标题】如何调试从外部应用程序调用的类库?【英文标题】:How to debug class library that called from external app? 【发布时间】:2012-12-02 19:13:34 【问题描述】:

有一个执行 C# 脚本并能够处理 DLL 文件(我的类库)的外部工作流。

是否可以将调试附加到我的类库项目,以便一旦这个 WF 调用它就会触发断点?

谢谢

【问题讨论】:

你有图书馆的来源吗?如果不是,您可以使用它在调试输出中抛出的异常。 见这里:***.com/questions/654696/… 我没有将调用我的库的应用程序的源代码。它只使用我的 DLL。所以***.com/questions/654696/… 确实打开了两种解决方案... nikolaMM94,如果我无法将调试附加到我的 DLL,exceptios 将如何提供帮助? 如果不可能并且我必须记录对象内容,请告诉我? 【参考方案1】:

是的,您可以使用 Visual Studio 执行此操作。你有两个选择:

配置您的项目以启动外部程序

    打开您的 DLL 项目。

    在项目的属性中,转到调试选项卡。

    选择 启动外部程序 并提供将调用您的 DLL 的外部程序的路径,以及您可能需要提供的任何命令行参数,以及工作目录(如果是)相关的。

    保存项目。

    在代码中您想要的位置设置断点。

    按 F5 开始调试。 (此时,您的断点会说它们不会被命中,因为符号未加载。暂时不用担心。)

    尽你所能让外部应用程序加载你的库并运行你的代码。

Visual Studio 将检测模块加载、加载符号并在断点处停止。

附加到现有进程

如果您无法启动该进程,而是必须附加到已在运行的进程,您也可以这样做:

(旁注:如果您使用的是 Visual Studio 的“Express”版本,我不认为它具有此功能,但我不确定。这很容易判断:您要么拥有下面第 4 步中提到的菜单项。)

    确保进程正在运行。

    打开您的 DLL 项目。

    设置断点等

    Debug 菜单中,选择 Attach to process...

    在出现的对话框中,找到列表中的进程,将其突出显示,然后单击附加

    Visual Studio 将进入调试模式。 (此时,您的断点会说它们不会被命中,因为符号未加载。暂时不用担心。)

    尽你所能让外部进程加载并运行你的代码。

Visual Studio 将检测外部进程中的模块加载、加载符号并在断点处停止。


注意在这两种情况下,如果外部进程从项目的 bin/Debug 文件夹以外的位置加载 DLL,则必须确保将 DLL 复制到其他位置 每次构建它时(您可以在项目选项中将其设置为自动发生)。否则,Visual Studio 将无法检测到正在加载的 DLL 是您要调试的那个。

【讨论】:

Crowser,对我来说,您描述的两种解决方案以不同的方式工作(Visual Studio 2013):附加到进程正确加载 PDB 并命中断点,而“启动外部程序”似乎根本不加载 PDB。当我转到 Debug>Windows>Modules 时,在这种情况下我找不到我的 DLL,但代码仍然按预期执行;只是断点没有命中。在启动外部程序期间加载 PDB 是否有任何细节? 我可以确认,对于 Visual Studio 2015 Express for Web,此功能可用。我能够附加到从 Linqpad 运行的查询。这不是一个显而易见的过程,但最终我选择了一个有效的过程。谢谢你的回答。【参考方案2】:

如果您不想/不能使用外部应用程序 - 您可以直接从 Visual Studio 调用类库:Ctrl+Alt+I 以显示 "Immediate" 寡妇,然后您可以从那里调用类库中的任何方法(使用断点)。您必须输入完全限定的名称(即命名空间)。

【讨论】:

谢谢!其他解决方案在我的特定用例中不起作用。【参考方案3】:

您可以使用 Debug 菜单中的 Attach to process 来调试您的 DLL 项目。如果本机代码不进行调试,您可能需要使用混合模式调试。这可以通过在附加到进程窗口中单击选择按钮时出现的窗口中选择托管和本机代码类型来完成。

如果您使用的 Visual Studio 版本支持宏,那么您可以使用以下代码创建一个新宏来自动执行所有这些操作:

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics

Public Module AttachToProcess

    Public Sub DebugMyDLL()
        DTE.ExecuteCommand("Build.BuildSelection")
        Dim ApplicationExePath As String = "C:\Program Files (x86)\foo\bar.exe"
        Shell(ApplicationExePath)
        Try
            Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
            Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
            Dim dbgeng(2) As EnvDTE80.Engine
            dbgeng(0) = trans.Engines.Item("Managed (v4.0)")
            dbgeng(1) = trans.Engines.Item("Native")
            Dim proc2 As EnvDTE80.Process2 = dbg2.GetProcesses(trans, "<QualifierName>").Item("bar.exe")
            proc2.Attach2(dbgeng)
        Catch ex As System.Exception
            MsgBox(ex.Message)
        End Try
    End Sub

End Module

上述宏尝试构建您的项目,启动外部应用程序,然后自动将您的 DLL 附加到该程序。您可以从 附加到进程 窗口获取系统的 QualifierName。此外,托管代码的版本(在本例中为“Managed (v4.0)”)取决于您使用的 .NET 框架的版本。

【讨论】:

【参考方案4】:

来自 Microsoft 的有用链接:Specify a calling app in a managed DLL project

    打开你的类库项目 转到[项目] 在底部选择项目的 [Properties...] 转到[调试] 在“启动”行中,选择“可执行文件” 选择 .exe 文件的路径 设置断点 运行项目。

来自 Microsoft 的链接有各种其他有用的调试方案。

我使用的是 Visual Studio 16.4.5。

【讨论】:

【参考方案5】:

我认为现在创建一个单元测试项目来执行你的库代码更为实际。因此,您将用一块石头杀死两只鸟:将能够在同一个解决方案中调试您的项目,顺便开始通过测试覆盖您的代码。

【讨论】:

以上是关于如何调试从外部应用程序调用的类库?的主要内容,如果未能解决你的问题,请参考以下文章

winform如何全局调用一个外部的类?

如何在 Visual Studio 中调试类库

如何从不同appdomain的类库中调用实例方法?

C#调用DLL问题

.NET:如何隔离反调试类库?

类库中的 HtmlEncode