【问题标题】:CLR Dll UI creating too many formsCLR Dll UI 创建了太多表单
【发布时间】:2019-04-15 14:05:09
【问题描述】:

所以我试图在 c++ 中创建一个 dll,它会在将表单注入进程时打开一个表单。

这是我拥有的代码(与为表单生成的文件分开的文件):

#include "Main.h"
#include <Windows.h>

using namespace::System;
using namespace::System::Windows::Forms;

auto FormRender(void) -> void {
    Hyperscanner::Main lpMain;
    lpMain.ShowDialog();

    return;
}

HANDLE g_Thread = nullptr;

auto __stdcall DllMain(HMODULE hMod, DWORD dwReason, void* lpReserved) -> int {
    if (dwReason) {
        g_Thread = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>
            (FormRender), nullptr, 0, nullptr);
    }

    if (!dwReason) {
        TerminateThread(g_Thread, 0);
        CloseHandle(g_Thread);
        FreeLibraryAndExitThread(hMod, 0);
    }

    return true;
}

问题在于,由于某种原因,当我将其注入进程时,它会不断创建表单,就像线程中有一个循环一样,但您可以看到没有一个循环。当我尝试正常调用它时,没有线程,它根本不会出现,这没有意义,因为它在技术上与线程内部的相同。

我想知道我做错了什么并且可以使用帮助。谢谢!

解决方案(@hacksalot):

问题是启动了很多线程,这些线程会通过我的 DllMain 回调,所以它会启动一堆线程(由于某种原因没有考虑检查创建了多少线程)。

为了解决这个问题,我添加了一个全局变量以确保它只执行一次。

#include "Main.h"
#include <Windows.h>

using namespace::System;
using namespace::System::Windows::Forms;

volatile int g_StartOnce = 0;

auto FormRender(void) -> void {
    Hyperscanner::Main lpMain;
    lpMain.ShowDialog();

    return;
}

auto StartRenderThread(HANDLE& ThreadHandle) -> bool {
    ThreadHandle = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>
        (FormRender), nullptr, 0, nullptr);

    if (ThreadHandle)
    {
        return true;
    }

    return false;
}

auto StopRenderThread(HANDLE& ThreadHandle) -> bool {
    if (ThreadHandle) {
        if (TerminateThread(ThreadHandle, 0)) {
            CloseHandle(ThreadHandle);
            return true;
        }
    }

    return false;
}

HANDLE g_Thread = nullptr;

auto __stdcall DllMain(HMODULE hMod, DWORD dwReason, void* lpReserved) -> int {
    if (dwReason && !g_StartOnce) {
        StartRenderThread(g_Thread);
        ++g_StartOnce;
    }

    if (!dwReason) {
        StopRenderThread(g_Thread);
        FreeLibraryAndExitThread(hMod, 0);
    }

    return true;
}

【问题讨论】:

    标签: c++ dll clr


    【解决方案1】:

    来自documentation

    您不应该在DllMain 中执行以下任务:

    ~致电CreateThread

    另外,FormRenderThreadProc 回调签名不匹配,其调用会导致堆栈损坏。我什至不会提及 CLR 的东西......

    【讨论】:

    • @VTT 所说的一切(有一个lot of stuff you shouldn't do from DllMain)另外,请注意if (dwReason) 将在每次创建线程时测试为真,而不仅仅是在第一次将 DLL 附加到进程时。这可能就是您看到“循环”行为的原因。通常我们会看到更明确的 if/switch 来区分进程和线程附加。
    • 你可能会在那里递归地创建线程,因为如果内存服务,DllMain 会为每个创建的线程调用所有加载的 DLL,DLL_THREAD_ATTACH 用于dwReason
    • @hacksalot 帮我解决了我的问题,但我不能接受他的回答,因为他只发表了评论,将通过解决方法更新 OP
    • 没关系,这一切都浮出水面,我有一段时间没看过这些东西了,所以我犹豫着要不要给出一个完整的答案。很高兴你解决了!
    猜你喜欢
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 2012-03-21
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多