我先把一个dll文件从A文件夹复制到B文件夹,紧接着我打开B文件夹并调用dll里的函数,没有成功。可我如果从复制dll开始,一直到调用dll里的函数完毕,一步一步的执行,复制文件完毕后,调用dll里的函数却可以成功,这是什么原因?我以为可能是复制文件需要时间,直接执行可能是没有复制完毕就开始调用dll里的函数,为了防止这种情况,我在复制完毕后Sleep(10000),这次直接执行,却发现还是不行,所以不是时间的问题,那会是什么原因呢?我实在想不出来了,请各位帮我分析一下吧。

解决方案 »

  1.   

    你在复制完毕后用FindFirstFile查找看一下能不能成功的?
      

  2.   

    在一个辅助线程内不能调用一个dll内的函数吗?
      

  3.   

    我的这个dll内的函数前一个修饰符WINAPI,为什么单步执行就能成功?尽管也是在辅助线程内?
      

  4.   

    工作目录与应用程序目录不在同一目录请如下检查一下
    在应用程序创建一个快方式,此时运行能成功
    将快捷方式移到工作目录(一般为.dsw,.cpp目录),再运行一下,不成功
    如果是上面情况,原因就是目录问题
      

  5.   

    不太像是目录的问题,理由如下:(我的程序大体结构如下)
    1、sdk程序。
    2、网络程序,基于TCP/IP,下面所写程序段是服务器端程序
    2、窗口过程大体如下:LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    case: WM_CREATE
       AfxBeginThread()//程序执行开始就创建一新线程,新线程名为B
    .....
    }
    UINT WINAPI B(..)//线程B
    {
      listen()//监听客户端连接
      Accept()//接收连接,这里可能需要阻塞(或挂起)一段时间.
      .......//判断是否有连接成功,如果连接成功,进入一个新线程C;
    }UINT WINAPI C(..)//线程C
    {
       case MY_COMMAND//连接成功后,客户端立即向服务器发送MY_COMMAND命令
            Function()//其中Function是dll内的函数。
    }
    问题就在Function()处,如果直接执行,程序不报错,但是Function()的功能根本没有执行。可是,如果你单步执行,执行完Function()这一条语句后,函数就能达到预期效果,这是一种情况。还有,如果把Function()放在主线程内(即窗口过程中),无论是不是单步执行,还是直接运行程序,都可以取得预期效果,这又是一种情况,还有一种情况,就是如果把Function()放在线程B内,也完全可以成功执行。所以,这样看来,只是在线程C内不能正确完成Function()的功能。这是什么意思呢?太奇怪了。值得注意的是,程序一开始运行后(即发出WM_CREATE消息后),线程A与线程B都执行了(从程序代码上可以看出来),而线程C却没有立即执行,因为线程B必须等待(阻塞或挂起)一段时间,等有了客户端的连接请求后,才有机会进入线程C,我觉得这里比较可疑,但却找不到充分的理由,也不知道怎么解决。请大家帮忙分析一下,感激!
      

  6.   

    没有错误代码,提示操作成功完成,但为什么Function达不到预期的效果?
    我的Function()功能是开始一键盘钩子的函数,当然,这个开始键盘钩子的函数(Function,核心是SetWindowsHookEx),是在dll内的,我事先已经将dll的导出函数,头文件等这些常规操作完成了。而且放在主线程内确实可以开始一键盘钩子。怎么到了C内就不开始了呢?而且,也没有错误提示,提示操作成功完成。但就是Function()的功能没有显示出来(不能开始键盘记录)。我把B的线程代码写在下面:
    UINT WINAPI AcceptThread(LPVOID lParam)
    { SOCKET socket;
    SOCKET acceptSock;
    CONNECTINFO connectInfo;
    THREADINFO acceptThreadInfo;
    SOCKADDR retAddr;
    SOCKADDR_IN retInAddr;
    WSAEVENT event[2]={0};
    WSANETWORKEVENTS wederYes; if(!LSdcerCreateSocket(&socket,SOCK_STREAM))
    {
    return -1;
    }
    if(!LSdcerBindSocket(socket,hostaddress,hostPort))
    {
    return -1;
    }
    if(!LSdcerListenSocket(socket))
    {
    return -1;
    } WSAEVENT workEvent=WSACreateEvent();
    if(WSA_INVALID_EVENT==workEvent)
    {
    LSdcerCloseSocket(socket);
    return -1;
    } event[0]=hExitEvent;
    event[1]=workEvent;
    if(WSAEventSelect(socket,workEvent,FD_ACCEPT)==SOCKET_ERROR)
    {
    WSACloseEvent(workEvent);
    LSdcerCloseSocket(socket);
    return -1;
    }
    SetEvent(hPrepareEvent); for(;;)
    { DWORD whichEvent=WSAWaitForMultipleEvents(2,event,FALSE,WSA_INFINITE,FALSE);
    if(whichEvent==WSA_WAIT_FAILED||whichEvent==WAIT_OBJECT_0)
    {
    WSACloseEvent(workEvent);
    LSdcerCloseSocket(socket);
    return -1;
    }
    int right=WSAEnumNetworkEvents(socket,workEvent,&wederYes);
    if(right==SOCKET_ERROR)
    {
    WSACloseEvent(workEvent);
    LSdcerCloseSocket(socket);
    return -1;
    }

    if(wederYes.lNetworkEvents==FD_ACCEPT)
    {
    int sockaddrret=sizeof(retAddr);
    acceptSock=WSAAccept(socket,&retAddr,&sockaddrret,0,0);
    if(acceptSock==INVALID_SOCKET)
    {
    continue;
    }
    else
    {
    memcpy(&retInAddr,&retAddr,sizeof(SOCKADDR_IN));
    strcpy(connectInfo.IP,inet_ntoa(retInAddr.sin_addr));
    connectInfo.sock=acceptSock; hSendReceiveHandle=NewThreads(SendReceiveThread,&connectInfo,&SendReceiveID);
    if(hSendReceiveHandle==0)
    {
    continue;
    }
    else
    {
    acceptThreadInfo.hThreadHandle =hSendReceiveHandle;
    acceptThreadInfo.ThreadID=SendReceiveID;
    EnterCriticalSection(&g_CriticalSection);
    threadList.push_back(acceptThreadInfo);
    LeaveCriticalSection(&g_CriticalSection);
    }
    }
    }
    }
    return 0;
    }
      

  7.   

    上面代码中:
    hSendReceiveHandle=NewThreads(SendReceiveThread,&connectInfo,&SendReceiveID);//为开始新线程C的语句。
    下面我再把C线的代码写下来:
    UINT WINAPI SendReceiveThread(LPVOID lParam)//线程C
    { CONNECTINFO *sockInfo=(CONNECTINFO*)lParam;
    SOCKET s=sockInfo->sock;

    WSAEVENT workEvent=WSACreateEvent();
    if(workEvent==WSA_INVALID_EVENT)
    {
    return -1;
    }
    DWORD retLen;
    NETCOMMAND comm;
    memset(&comm,0,sizeof(NETCOMMAND));
    if(!LSdcerRecvDataS(s,(char*)&comm,sizeof(NETCOMMAND),&retLen,workEvent,SNDRCVTIME_OUT))
    {
    WSACloseEvent(workEvent);
    LSdcerCloseSocket(s);
    DeleteThread(GetCurrentThreadId());
    return 0;
    }
    switch(comm.commandID)
    {
    case WM_COMAND:
                   Function()/////在这里面调用dll的操作
               break;...//结束本线程的操作。
    }void Function()
    {
    //////调用dll内的函数(开始一键盘钩子),如果单步执行完这一步,完全可以实现我的功能,但只要是直接运行,不报错,功能没有。
    }
      

  8.   

    不要用隐式Dll调用,
    改成显式Dll调用试试。
    先定义函数指针:
    typedef VOID (*MYPFUN)(); 
    然后将
    switch(comm.commandID)
    {
    case WM_COMAND:
                   Function()/////在这里面调用dll的操作
               break;
    改为
    switch(comm.commandID)
    {
    case WM_COMAND:
             {
                HINSTANCE hinstLib;
                hinstLib=LoadLibrary(yourpath+"\\b\\fuckyou.dll");
                if (hinstLib == NULL) 
                {
                   AfxMessageBox("fuck you!!, the handle of the dll is invalid!!");
                   return;
                 }
                 ProcFun = (MYPFUN) GetProcAddress(hinstLib, "MyFun"); 
                 if (ProcFun == NULL) 
                 {
                    AfxMessageBox("fuck you!!, the handle of the fun is invalid!!");
                    return;
                  }  
                  ProcFun();//调 用你的函数。
                  FreeLibrary(hinstLib);   
                
              }
               break;
      

  9.   

    问题不知道是不是出在这里;
    你是sdk程序,反正我在sdk程序中用AfxBeginThread,编译都不能通过,因此请改用CreateThread来抛线程(记住CloseHandle),可能就OK了;
      

  10.   

    另外我在您的代码中看到许多afx打头的函数,都去掉吧;
      

  11.   

    成功了,成功了,但还是不解。按照lzzqqq(Jonersen)的代码,再加个Sleep(5000)
    switch(comm.commandID)
    {
    case WM_COMAND:
             {
                HINSTANCE hinstLib;
                hinstLib=LoadLibrary(yourpath+"\\b\\fuckyou.dll");
                if (hinstLib == NULL) 
                {
                   AfxMessageBox("fuck you!!, the handle of the dll is invalid!!");
                   return;
                 }
                 ProcFun = (MYPFUN) GetProcAddress(hinstLib, "MyFun"); 
                 if (ProcFun == NULL) 
                 {
                    AfxMessageBox("fuck you!!, the handle of the fun is invalid!!");
                    return;
                  }  
                  ProcFun();//调 用你的函数。
                  Sleep(5000);//这条语句是我自己加的,我的函数竟然实现了其功能。看来是时间的问题,可是没道理呀?我的线程C中,调用ProcFun()后,会自动删除自己的线程(C线程句柄),可是这是在ProcFun()执行以后才删除的呀。难道是ProcFun()还没有执行完毕,其所在的线程就被删除了?有这种可能吗?好比是如下程序段:
    f()
    { dllFunc();//调用库里的函数
      deletethread//删除线程,虽然这一句是删除线程的语句,但是它是在dllFunc()后,有没有可能是直接运行的时候,dllFunc()没有执行完成就执行了deletethread(删除线程)的语句呢?这有可能吗?我觉得肯定是得先完成dllFunc()的操作后才执行deletethread呀?不是吗?怎么回事?
                  FreeLibrary(hinstLib);   
                  break;
    .......删除本线程句柄
                
              
      

  12.   

    我明白了,我彻底明白了,多谢各位,多谢梅大姐在天保佑!!!!!是这样的:因为调用的是设置键盘钩子的函数,而C线程中,虽然确实开始了键盘钩子,但是由于线程C在执行完开始键盘钩子的操作后,马上就自动删除了,而既然是一个钩子程序,则包含SetWidnowsHookEx()的模块就不能退出,但事实上这个C线程在SetWindowsHookEx()被调用后,瞬间就被killed了。所以,键盘钩子只存在了一瞬间,所以我们永远捕捉不到任何键盘消息(准确的说是能捕捉到键盘记录的时间只有一瞬间),所以,不是时间的问题,也不是同步的问题。而是SetWindowsHoodEx(即我上面调用的Function()),绝不能退出。呵呵,希望能给大家点经验,以后不要犯我这样的低级错误。一会结贴。