UINT MyNewThread(LPVOID)
{
AfxMessageBox("MyNewThread Is Begin");
return true;
}
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
    AfxBeginThread(MyNewThread,NULL);
         }
}
这个DLL为什么不能正常运行呢??
在资源管理器中能看到程序已经运行,但 主调的EXE 程序 不显示界面,这是怎么回事呢??
如果把AfxBeginThread(MyNewThread,NULL);换成AfxMessageBox("hello");程序就可以正常运行,
难道在DLLMAIN中不能启动新线程吗???

解决方案 »

  1.   

    线程中弹出窗口“AfxMessageBox("MyNewThread Is Begin");”会阻塞主线程中的消息循环。所以最好不要在线程中弹出窗口,真的要弹出窗口也一定要处理消息的传递。
      

  2.   

    You should know that,AfxBeginThread(MyNewThread,NULL) is a thread,not a DLL_PROCESS_ATTACH, therefore, the reason should be DLL_THREAD_ATTACH,so    
           if (dwReason == DLL_THREAD_ATTACH )
    {
        AfxBeginThread(MyNewThread,NULL);
             }
      

  3.   

    呵呵,搂上的说的有道理。^0^, 。
     
        本人有另外一个问题:(有关类的汇出问题)
     
        我在用类编写DLL的时候,发现所汇出的api,可以被VC动态或者静态调用,而不能被C++ Builder调用,请问各位是何原因??? (我已经便要了适应BCB环境下的lib文件)    先谢啦!
      

  4.   

    to : vcleaner(我没做大哥已经很久了.......)////////////////////////////////////////////
    class CDllFun : public CWinThread
    {
    DECLARE_DYNCREATE(CDllFun)
    protected:
    CDllFun();          
    public:
    public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();.......};
    BOOL CDllFun::InitInstance()
    {
    AfxMessageBox("MyNewThread Is Begin");
    return TRUE;
    }DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        AfxBeginThread(RUNTIME_CLASS(CDllFun));  //注意此处:)
             }
    }////////////////////////////////////////
    上面的处理方法不会有问题吧?但还是不行啊!现像与一贴一样! 
    **************************************************************************************
    TO :dafan(大帆) 
    用你的方法也不行啊!!虽然看到主调程序EXE的界面了!但"MyNewThread Is Begin"这个消息没有出现啊!***************************************************************************************
    TO :dafan(大帆) 
    你提问的问题 是不是由于函数调用格式的原因?试试用extern"c"看看
    ***************************************************************************************谢谢各位的帮助!:)
      

  5.   

    to  ker0(无敌的傻瓜) :      在函数汇出的时候我都已经用了extern"c",VC都是好好的工作,  的做法是:
      
             #ifdef  MYDLL_EXPORTS
             #define MYDLL_API __declspec(dllexport)
             #else
             #define MYDLL_API __declspec(dllimport)
             #endif         #include "windows.h"
             #ifdef __cplusplus
             extern "C"
             {
             #endif         // This class is exported from the AutoMAC_Client.dll
             class MYDLL_API CMYDLL
             {
                   public:
                        CMYDLL(void);
              ~MYDLL(void);                   void WINAPI Fun();
            }        #ifdef __cplusplus
            }
            #endif
               void WINAPI Fun()
            {
                .......
             }        当然,上面不是我的Source Code,但是类似。
      

  6.   

    TO: dafan(大帆) BCB我没用过,你把整个类都导出来了,是不是在导出时处理为pascal的调用约定??(BCB用的是VCL库,它与MFC能很好的沟通吗,猜想的),不过这样也太~~~~~~。
    BCB的提示是什么??
      

  7.   

    记得很久以前在一本叫advanced windows programming 的书上看到的,在DLLMain函数中不能启动线程,原因是:OS对DLLMain的调用是序列化的(或者叫串行化),启动线程时系统要调用DLLMain,传给它DLL_THREAD_ATTACH 参数,而你在DLLMain中启动线程,由于串行化的关系,系统无法再次调用DLLMain,发生死锁。
      

  8.   

    TO: earthquake(earthquake) 谢谢你的答复!可能真的是这样的!不过一些木马的远程DLL植入是怎么启动线程的呢??用CreateRemoteThrea这个函数加载DLL,我想只能在DLLMAIN中激活新线程.不知道是怎么实现的?
      

  9.   

    我用某种工具发现,DLL里面的API函数都有了,但是显示为【LINK Error】unresolved external ........。 
        请看我用工具抓到的结果:     在VC中的
                  5  _MYDLL_Message_Out@4
                  2  _MYDLL_Client_Init@0
                  0  _MYDLL_ClientClose@0
                  6  _MYDLL_Return_MACAddress@0
                  3  _MYDLL_Client_Status@0
                  7  _MYDLL_TestProgram_Status@4
                  4  _MYDLL_GetMACInfo@12
                  1  _MYDLL_ClientGetInfo@8
                  8  _ClientScanMAC@4      在BCB中:
                  0  _MYDLL_ClientClose@0
                  0  _MYDLL_ClientGetInfo@8
                  0  _MYDLL_Client_Init@0
                  0  _MYDLL_Client_Status@0
                  0  _MYDLL_GetMACInfo@12
                  0  _MYDLL_Message_Out@4
                  0  _MYDLL_Return_MACAddress@0
                  0  _MYDLL_TestProgram_Status@4
                  0  _ClientScanMAC@4        它们都一样的,前面的数字表示该函数在dll中的相对序号,由于BCB中的函数是按顺序下来的,所以它全为0。
            
             还有,我用另外一个方法编写了这个dll,没有用类,结果ok,可以编译执行。我也用该工具看了它的汇出函数,内容都是一样的。         结果一样,为什么会发送LINK错误???
      

  10.   

    我用某种工具发现,DLL里面的API函数都有了,但是显示为【LINK Error】unresolved external ........。 
        请看我用工具抓到的结果:     在VC中的
                  5  _MYDLL_Message_Out@4
                  2  _MYDLL_Client_Init@0
                  0  _MYDLL_ClientClose@0
                  6  _MYDLL_Return_MACAddress@0
                  3  _MYDLL_Client_Status@0
                  7  _MYDLL_TestProgram_Status@4
                  4  _MYDLL_GetMACInfo@12
                  1  _MYDLL_ClientGetInfo@8
                  8  _ClientScanMAC@4      在BCB中:
                  0  _MYDLL_ClientClose@0
                  0  _MYDLL_ClientGetInfo@8
                  0  _MYDLL_Client_Init@0
                  0  _MYDLL_Client_Status@0
                  0  _MYDLL_GetMACInfo@12
                  0  _MYDLL_Message_Out@4
                  0  _MYDLL_Return_MACAddress@0
                  0  _MYDLL_TestProgram_Status@4
                  0  _ClientScanMAC@4        它们都一样的,前面的数字表示该函数在dll中的相对序号,由于BCB中的函数是按顺序下来的,所以它全为0。
            
             还有,我用另外一个方法编写了这个dll,没有用类,结果ok,可以编译执行。我也用该工具看了它的汇出函数,内容都是一样的。         结果一样,为什么会发送LINK错误???难道BCB不能接受用类编写的DLL???/
      

  11.   

    to:dafan(大帆)
    虽然都是C++语言,但VC和BCB对C++类的实现是不一样的,BCB要想调用VC写的DLL,则该DLL必须输出标准的WINAPI调用模式的函数,BCB才能懂得如何去调用该函数。你说的输出类的DLL应该是VC的扩展DLL,不是标准DLL,只能由VC写的程序自己调用。
      

  12.   

    to:ker0(无敌的傻瓜)
    创建远程线程的步骤:
    1、找到目标(宿主)进程
    2、打开该进程,在该进程地址空间内申请一块空间
    3、向该空间内写入你的代码
    4、调CreateRemoteThread创建远程线程(运行于宿主进程空间内,线程函数就是你写入的代码)然后,你想干什么就干什么吧,呵呵。
    当然,还有很多细节,需要你自己慢慢研究滴......
      

  13.   

    TO:dafan(大帆)
    我觉的 earthquake(earthquake)说的很有道理!一个是MFC为基础的,一个是以VCL为基础的!想通用的话必须编译成通用格式,特别是VCL是PASCAL语言为基础的,所以有很多不通用的地方。你这样试试
    不用隐式方式调用,用LOADLIBRARY显式方式看看也不行吗??如果行,你就重点处理一下LIB文件再试试。
      

  14.   

    TO: earthquake(earthquake) 
      我就是因为前几天看到了这个类似的网文,想仔细研究一下,结果不成功:)
    进行到第4步也成功了,被注入的进程只是多了个DLL调用而已,并没有达到执行程序的目的啊,
    DLL被加载了,DLLMAIN返回后就没戏了,所以想让DLL做我们想干的事儿,必须在DLLMAIN中启动一个类似UI的具有消息循环的线程才行,但是我怎么试试都不行,在DLLMAIN执行一个普通和函数还可以,但一涉及到AfxBeginThread这个函数,主调程序就没界面了????什么原因??不明白:(
      

  15.   

    既然dll加载都成功了,还有什么不能干呢?你可以在dll加载后调用一个该dll输出的函数啊。
      

  16.   

    用谁来调用呢???DLL自己没有消息循环,很被动啊
      

  17.   

    我做过在dllmain中创建线程,不过我用的是标准的CreateThread,很好用。
      

  18.   

    TO: agchen81(吾将上下尔求索) 用CreateThread函数怎样启动用启界面线程呢?
      

  19.   

    用谁来调用呢???DLL自己没有消息循环,很被动啊
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    你的远程线程是怎么写得?
    把流程写出来,用伪代码也可以
      

  20.   

    刚才试了一下,如agchen81(吾将上下尔求索)所说,在Dllmain中确实可以创建线程,ULONG WINAPI Thread(void *p)
    {
    OutputDebugString("Dllmain create this thread\n");
    return 0;
    }BOOL APIENTRY DllMain(HANDLE hModule,
      DWORD  ul_reason_for_call,
      LPVOID lpReserved)
    {
    DWORD dwTID;
    HANDLE hThread;

             if (ul_reason_for_call == DLL_PROCESS_ATTACH)
    {
    hThread = CreateThread(NULL, 0, Thread, 0, 0, &dwTID);
    CloseHandle(hThread);
    }    return TRUE;
    }如果把if (ul_reason_for_call == DLL_PROCESS_ATTACH)换成
    if (ul_reason_for_call == DLL_THREAD_ATTACH)则界面死掉。分析:
    你是创的远程线程,在远程线程中动态加载DLL,这时系统不会用DLL_PROCESS_ATTACH来调dllmain,而是DLL_THREAD_ATTACH。
      

  21.   

    //c:\MyDllFile.dll
    #include "一个从 CWinThread 派生出来的类,有消息循环 .h" DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
       switch()
      {
        case DLL_PROCESS_ATTACH:
        AfxBeginThread(RUNTIME_CLASS(一个从 CWinThread 派生出来的类,有消息循环 ));
        .....
      }
       return ;
    }//远程线程
    main()
    {
    1. hRemProcID=用toolhelp找到explorer.exe ID;
    2. 目标句柄=OpenProcess(hRemProcID);
    3. 远程内存=VirtualAllocEx(目标句柄,len("c:\\MyDllFile.dll"));
    4. 将"c:\\MyDllFile.dll"写入“远程内存”;
    5. 找到 LoadLibraryW 函数的入中地址;
    6. 启动远程线程;
    return true;
    }
    在第6步时,DLL就会被导入远程进程中,但是如果不在DLLMAIN中启动新线程,等DLLMAIN返回后 我实在想不出再怎样调用我们自己设计的函数!
       (难道还可以加个第7步(启动MyDllFile中的MyFun),自己猜的)
      

  22.   

    我把我做的win32的dll改写为MFC的DLL,相应在InitInstance()中创建线程,并在线程函数中DoModal一个对话框,用对话框来处理消息。并且可以通过代码将对话框隐藏的无影无踪,在任务管理器和进程列表中都看不到任何痕迹。
      

  23.   

    TO:agchen81(吾将上下尔求索)
      AfxBeginThread();这个函数有两个用法,其中一个就是用来创建用启界面线程的!我现在不敢用CreateThread这个函数,主要还不会用它来调用 基于MFC的函数(没看明白 RUNTIME_CLASS 这个宏。)你用CreateThread时传给它什么参数?是把InitInstance()传给它了吗??
      

  24.   

    to: ker0(无敌的傻瓜)DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
       switch()
      {
        case DLL_PROCESS_ATTACH:  // 可能问题出在这里,这个分支不会走到,因为从线程动态加载dll时,系统不会用DLL_PROCESS_ATTACH来调用dllmian
        AfxBeginThread(RUNTIME_CLASS(一个从 CWinThread 派生出来的类,有消息循环 ));
        .....
      }
       return ;
    }
      

  25.   

    InitInstance(){~~~~~~~~~~~~~~~~~~~
    ::CreateThread( 
    NULL,                        // default security attributes 
    0,                           // use default stack size  
    ThreadFunc1,                  // thread function 
    NULL,                // argument to thread function 
    0,                           // use default creation flags 
    NULL);                // returns the thread identifier
    ~~~~~~~~~~~~~
    }
      

  26.   

    if (dwReason == DLL_PROCESS_ATTACH)
    {
    AfxBeginThread(RUNTIME_CLASS(CDllFun));
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    { }
      else if (dwReason == DLL_THREAD_ATTACH)
    { // AfxBeginThread(RUNTIME_CLASS(CDllFun));

    }
    return 1;   // ok
             }这是我的源码(用MFC AppWizard(DLL)建的)让我删了一些注解和断言,两个地方我都用了!可不好用啊,下断点后,F10一过后,AfxBeginThread(RUNTIME_CLASS(CDllFun));就不返回了!
    不过在任务管理器中可以看到这个程序有两个进程了!(莫名其妙)
    你可以试试,不麻烦,我现在用普能的EXE文件调用,也不行!(EXE文件没界面了)我的验证思路是这样的:
    建一个EXE对话框;
    建一个DLL文件,加入一个对话框类;
    在DLLMAIN中启动一个UI线程,显示DLL中的对话框 AfxBeginThread(RUNTIME_CLASS(CDllFun));。EXE文件调用,显示两个对话框。谢谢两位帮助!:)
      

  27.   

    TO:agchen81(吾将上下尔求索)你在DLLMAIN中是怎么调用的呢?
    DLLMAIN(...)
    {
     ...
     Class obj;
     obj.InitInstance()  //是这样?
     ...
    }
      

  28.   

    试了下,用AfxBeginThread确实不行,流程走到类CWinThread的构造函数以后就被锁住了。估计是MFC内部管理数据结构时发生了死锁。用CreateThread就没问题。
    下面的代码你可以试试,我这里是成功了的。
    // 线程函数,用于显示对话框
    ULONG WINAPI Thread(void *)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState()); CMyDlg obj;// 对话框类 obj.DoModal(); return 0;
    }// dll的初始化函数
    BOOL CAfxdllApp::InitInstance() 
    {
    // TODO: Add your specialized code here and/or call the base class
             ::CreateThread(NULL, 0, Thread, 0, 0, NULL);

    return CWinApp::InitInstance();
    }
      

  29.   

    把DLL编译为release,在C++ Builder使用动态调用,我一直这么用的
      

  30.   

    TO:earthquake(earthquake)
       
      在DLLMAIN中怎么个调用法?涉及到SDK+MFC我就发怵// 线程函数,用于显示对话框
    ULONG WINAPI Thread(void *)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState()); CMyDlg obj;// 对话框类 obj.DoModal(); return 0;
    }// dll的初始化函数
    BOOL CAfxdllApp::InitInstance() 
    {
    // TODO: Add your specialized code here and/or call the base class
             ::CreateThread(NULL, 0, Thread, 0, 0, NULL);

    return CWinApp::InitInstance();
    }
    ///////////////////////////////////////////////
    DLLMAIN(...)
    {
     ...
    case DLL_PROCESS_DETACH :
          {
           CAfxdllApp obj;
           obj.InitInstance()  //是这样?
          }
     ...
    }
    ///////////////////////////////////////////////
      

  31.   

    earthquake(earthquake)老师:
      
       能把你的实验工程文件打包送给我吗?
    我看看。.cn