如何在C中执行DLL中的线程

如何在C中执行DLL中的线程,c,windows,dll,C,Windows,Dll,我创建了一个运行3个工作线程的DLL,主线程在一个循环中等待线程完成。创建线程,但不执行线程 我曾尝试在使用CreateThread()创建的函数中设置MessageBox函数,但该框没有出现。我还尝试过调试,CreateThread()的返回值是有效的,因此线程被创建 BOOL WINAPI DllMain() { main(); return 1; } int main() { HANDLE h1, h2, h3; h1 = CreateThread(firs

我创建了一个运行3个工作线程的DLL,主线程在一个循环中等待线程完成。创建线程,但不执行线程

我曾尝试在使用CreateThread()创建的函数中设置MessageBox函数,但该框没有出现。我还尝试过调试,CreateThread()的返回值是有效的,因此线程被创建

BOOL WINAPI DllMain() {
   main();
   return 1;
}

int main() {
    HANDLE h1, h2, h3;

    h1 = CreateThread(first)...
    h2 = CreateThread(second)...
    h3 = CreateThread(third)...

   WaitForSingleObject(h3, INFINITE);
   return 1;
}

first() {
    MessageBoxA("print some stuff");
    return;
}
我已经包含了一些布局外观的伪代码。我无法提供真正的代码,因为它的敏感性。然而,这就是正在发生的事情。我在另一个加载此.DLL的项目中使用LoadLibrary。加载DLL并执行DllMain。然后它调用我的主函数,该函数创建3个线程。每个线程都被创建。但是线程内部的内容不会执行

编辑:

//dllmain.cpp:定义DLL应用程序的入口点。
#包括
void mb(){
MessageBoxW(0,L“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
}
void create(){
汉代;
德沃德·特莱德;
han=CreateThread(NULL、0、mb、NULL、0和线程ID);
han=CreateThread(NULL、0、mb、NULL、0和线程ID);
han=CreateThread(NULL、0、mb、NULL、0和线程ID);
}
布尔·阿皮恩特·德莱曼(){
创建();
返回1;
}
重点是我的)声明:

调用需要Kernel32.dll以外的dll的函数可能会导致难以诊断的问题。例如,调用User、Shell和COM函数可能会导致访问冲突错误,因为某些函数会加载其他系统组件。相反,在终止期间调用此类函数可能会导致访问冲突错误,因为相应的组件可能已经卸载或未初始化

驻留在User32.dll中,因此它是未定义的行为(这意味着在不同的情况下,它可能会工作,可能会出现故障,或者可能会崩溃)

此外,正如@RbMm所注意到的,WaitForSingleObject不属于那里。我也不确定CreateThread(但我找不到任何官方文件来确认/削弱它)


出于好奇,您能否添加一个
printf(“main called.\n”)
在main中,要查看调用了多少次?

因为在一般情况下可以卸载DLL,所以需要添加对DLL的引用-因为只有执行使用它的线程才能卸载它的代码。这可以通过调用来完成-增加模块的引用计数,除非指定了
GET\u module\u HANDLE\u EX\u FLAG\u UNCHANGED\u REFCOUNT
。当线程退出时,我们通过调用解除对DLL代码的引用。等待所有线程退出,在大多数情况下不需要。所以代码,里面的dll可以是下一个

ULONG WINAPI DemoThread(void*)
{
    MessageBoxW(0, L"text", L"caption", MB_OK);
    // dereference dlll and exit thread
    FreeLibraryAndExitThread((HMODULE)&__ImageBase, 0);
}

void someFnInDll()
{
    HMODULE hmod;
    // add reference to dll, because thread will be use it
    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (PCWSTR)&__ImageBase, &hmod))
    {
        if (HANDLE hThread = CreateThread(0, 0, DemoThread, 0, 0, 0))
        {
            CloseHandle(hThread);
        }
        else
        {
            // dereference dll if thread create fail
            FreeLibrary(hmod);
        }
    }
}


在dll入口点内等待是错误的,因为我们在这里持有进程范围的关键部分。如果我们等待线程退出-这个等待总是死锁-线程在退出(和启动)之前尝试进入这个关键部分,但不能,因为我们在这里等待他。所以我们保持关键部分并等待线程,但当我们退出这个关键部分时线程会等待。死锁

DllMain调用main?当.dll加载到一个应用程序(有另一个main)中时,可能会调用它?这最初是一个.exe程序,这就是为什么我有main。我甚至尝试过将“main”改为“startmain”和相同的行为。你不能运行.dll。你必须创建一个使用(链接或动态加载)它的.exe。您可能在.dll中有函数实现,但调用它们应该从.exe中进行(而不是在DllMain中)。是的,我知道。我在我原来的帖子中提到了这一点。我使用另一个加载.dll的项目。加载此dll的另一个程序只是执行一个LoadLibrary,加载后立即启动此dll。您这样做是错误的。阅读我在上一篇评论中包含的链接。你能把它放在我文章底部的例子中吗?我正试图把它融入到我所知道的事情中&__ImageBase不工作。这是导入吗?@Doritos-
EXTERN\u C EXTERN IMAGE\u DOS\u HEADER\u\u ImageBase是link.exe的特殊符号。但是,您(若使用另一个链接器)可以在dll入口点中创建并记住自映像库,并将其保存在全局变量中。
ULONG WINAPI DemoThread(void*)
{
    MessageBoxW(0, L"text", L"caption", MB_OK);
    // dereference dlll and exit thread
    FreeLibraryAndExitThread((HMODULE)&__ImageBase, 0);
}

void someFnInDll()
{
    HMODULE hmod;
    // add reference to dll, because thread will be use it
    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (PCWSTR)&__ImageBase, &hmod))
    {
        if (HANDLE hThread = CreateThread(0, 0, DemoThread, 0, 0, 0))
        {
            CloseHandle(hThread);
        }
        else
        {
            // dereference dll if thread create fail
            FreeLibrary(hmod);
        }
    }
}