Интерфейс CLR Dll создает слишком много форм

Итак, я пытаюсь создать 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;
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

От документация:

You should never perform the following tasks from within DllMain:

~ Call CreateThread.

Также FormRender не соответствует сигнатуре обратного вызова ThreadProc, и его вызов вызывает повреждение стека. Я даже не буду упоминать про CLR ...

Все, что сказал @VTT (есть много вещей, которые вы не должны делать из DllMain), плюс имейте в виду, что if (dwReason) будет проверять истину каждый раз, когда создается поток, а не только когда DLL впервые присоединяется к процессу. Возможно, поэтому вы видите "зацикливание". Обычно мы видим более явный переключатель if /, чтобы различать присоединение процесса и потока.

user4942583 12.11.2018 22:00

Вы можете рекурсивно создавать потоки там, поскольку DllMain вызывается для всех загруженных DLL для каждого созданного потока, если память обслуживает, с DLL_THREAD_ATTACH для dwReason.

user4942583 12.11.2018 22:02

@hacksalot помог мне решить мою проблему, но я не могу принять его ответ, так как он только оставил комментарий, обновит OP с разрешением

SoLux 12.11.2018 22:20

Ничего страшного, все получается в стирке, и я давно не смотрел на это, поэтому не решался дать полный ответ. Рад, что ты решил эту проблему!

user4942583 12.11.2018 22:22

Другие вопросы по теме