【问题标题】:Why VS2017 debugging will not stop at dllmain breakpoint?为什么VS2017调试不会停在dllmain断点?
【发布时间】:2020-01-10 01:12:01
【问题描述】:

我是第一次构建一个 dll,一切都按预期工作,但我无法调试它。

我做了一个尽可能最小的例子,只有一个 dllmain() 并使用 windows DLL(非 MFC)向导设置项目。

活动构建配置:x86 调试

右键项目->设置为启动项目

禁用预编译头文件

项目属性 -> 调试 -> 命令 -> 输入的应用程序可执行文件路径

Generate Debug Info 是的

这是整个 DLL,没有其他源文件或头文件。当我按 F5 时,应用程序运行并加载 dll,消息框触发。如果调试中断未注释,则不会触发消息框,并且 DLL 不会执行任何操作,但会成功加载。调试器不会中断。如果使用断点,则不会中断。

应用程序肯定正在加载我正在构建的 DLL。

.pdb 文件在那里并且正在生成。

我尝试将调试器更改为混合、自动、本机,但仍然无法正常工作。 CALLING 应用程序可能是用 C# 编写的,但它不是我的。

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{

//  __debugbreak();

    MessageBoxA(NULL, "Hit DLLMAIN", "test", MB_OK);

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

我做了很多研究,但我不知道为什么它不能调试。

更新:我编写了一个程序来调用 DLL 上的 LoadLibrary,并修改了我的项目以将该程序作为命令调用。

它进入调试器就好了。即使我将加载程序更改为发布配置。

不管是什么问题,都可能是第三方程序加载了dll造成的。

编辑:这是尝试使用第三方程序调试我的 dll 时的调试控制台输出,尽管程序继续运行,但调试器似乎出于某种原因退出。

'Program.exe' (Win32): Loaded 'C:\Users\Tech1\AppData\Local\ProgramDir\Program.exe'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ntdll.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\kernel32.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\KernelBase.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\user32.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\win32u.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\gdi32.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\gdi32full.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcp_win.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ucrtbase.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\imm32.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\Private_API.dll'. Module was built without symbols.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcrt.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\advapi32.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\sechost.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\rpcrt4.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\sspicli.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\cryptbase.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\bcryptprimitives.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\apphelp.dll'. Cannot find or open the PDB file.
'Program.exe' (Win32): Loaded 'C:\Windows\SysWOW64\kernel.appcore.dll'. Cannot find or open the PDB file.
The thread 0x4610 has exited with code 0 (0x0).
The thread 0x2614 has exited with code 0 (0x0).
The thread 0x45c0 has exited with code 0 (0x0).
The program '[21792] Program.exe' has exited with code 0 (0x0).

【问题讨论】:

  • 使用 MessageBox 调试代码是个坏主意。在 DllMain() 中使用它是非法的,如果尚未加载 user32.dll,那么您的程序将死锁。使用 NULL 作为第一个参数很麻烦,对话框需要一个所有者窗口位于其顶部,如果找不到桌面成为所有者的窗口。使您可能看不到它,因为它与另一个窗口重叠。当 debugbreak() 导致焦点改变时随机看到它。您确实需要让调试器断点工作以取得任何真正的进展,很多关于此的现有问题。
  • @HansPassant 我通过编写一个程序来加载 dll 并使用它来使调试器工作。我同意 MB()。我开始将 AllocConsole 与 freopen stdout 一起使用,但试图理顺 DLL 入口/出口,因此我不会重复分配或打开。您认为什么可能会阻止 VS 通过第三方应用程序进行调试?
  • @HansPassant - 如果 user32.dll 尚未加载,那么您的程序将死锁。 - 即使 user32.dll 尚未加载 -程序将不会死锁。在加载器锁中加载 dll 从不死锁,因为我们的线程已经拥有这个加载器锁。只有当我们开始 wait 说另一个线程并且该线程尝试进入加载程序锁时,才会出现死锁。
  • @user10530562 有趣的是,我创建了一个程序来尝试重现您的情况。我不知道我是否理解错误。如果debugbreak没有注释,debugbreak会起作用并触发断点提醒,看起来和你遇到的不一样。那我继续,程序就可以执行到Messagebox了。
  • @StriveSun-MSFT 嘿,谢谢你的关注。我今天又看了一遍,似乎调试器在启动后立即分离,但程序仍在运行。请查看我对帖子的更新。

标签: c# visual-studio winapi dll visual-studio-debugging


【解决方案1】:

这不是一个确定的答案,但我一直在调试原生 DLL,我有几个建议:

1) 如果使用该 DLL 的应用程序仍然存在,并且您知道如何让它再次尝试访问该 DLL,您也可以尝试“调试->附加到进程”。

2) 确保当您按 F5 进行调试时,您的 DLL 没有重新编译自身。我曾经有一个静态库依赖,导致 DLL 在每次调试时都重新编译。还有一个移动步骤,在编译时将 DLL 移动到目标应用程序的可执行文件夹中。这导致调试器认为我没有使用完全相同版本的 DLL。这可能是一个时间问题。如果有移动步骤,DLL版本必须是完全相同的编译。

【讨论】:

    猜你喜欢
    • 2021-07-21
    • 2014-04-12
    • 2016-11-19
    • 1970-01-01
    • 2023-03-12
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多