最新消息

[公告2014/05/30] 如有需要將部落格中,任何一篇文章的程式碼使用在商業用途,請與我聯繫。

[公告2015/04/26] Line版的 iInfo程式與投資應用 群組已上線想加入的朋友們,請先查看 "入群須知" 再與我聯繫 Line : aminwhite5168,加入請告知身分與回答 "入群須知" 的問題。

[公告2018/04/22] 台北 Python + Excel VBA 金融資訊爬蟲課程,課程如網頁內容 金融資訊爬蟲班:台北班 Python 金融資訊爬蟲、EXCEL VBA 金融資訊爬蟲

[公告2019/01/08] 請注意:我再次重申,部落格文章的程式碼,是要提供各位參考與學習,一旦網頁改版請自行修改,別要求東要求西要我主動修改,你們用我寫東西賺錢了、交差了,請問有分我一杯羹嗎?既然賺錢沒分我,請問有什麼理由要求我修改,如果沒能力改,就花錢來找我上課。

[公告2019/12/01] 若各位有 Excel VBA 案子開發需求,歡迎與我聯繫,可接案處理。

[公告2020/05/22] 頁面載入速度慢,起因為部分JS來源(alexgorbatchev.com)失效導致頁面載入變慢,目前已做調整,請多見諒。

2013年9月15日 星期日

VC使用Delay Load dll操作MFC100.dll

使用DLL會常遇到一些問題,就是相同名稱的DLL,分x86與x64版本時,如果用錯版本系統將丟出錯誤訊息框顯示,或是DLL中並沒有需要使用的函數。前者可用PE檔案格式可以抓出版本的問題,但後者就可能沒辦法順利抓出所需要的訊息。
如果真的想要抓出DLL錯誤的內容可以使用從VC6時就已經添加的功能Delay Load DLL來幫助我們達成目標,至於如何使用,就讓我們繼續看下去。
以下使用執行程式常用到的Windwos DLL(MFC100.dll、MSVCR100.dll、MSVCP100.dll)來做試驗與實際操作的部份做介紹。
後續再介紹自行開發DLL使用Delay Load DLL的差異。
#include <windows.h>
#include <delayimp.h>
#pragma comment(lib, "Delayimp.lib")

//#pragma comment(linker, "/DelayLoad:mfc100.dll") //將DelayLoad直接放在CPP中,經證實這種做法不可行
//#pragma comment(linker, "/Delay:unload")

CWinApp theApp;

FARPROC WINAPI DelayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
 printf("DelayLoadHook:\n");

    switch (dliNotify)
    {
  case dliStartProcessing:
   printf("\tdliStartProcessing...\n");
   // If you want to return control to the delay-load helper, return 0. 
   // Otherwise, return a pointer to a FARPROC helper function that will 
   // be used instead, thereby bypassing the rest of the helper.
   break;
   
  case dliNotePreLoadLibrary:
   printf("\tdliNotePreLoadLibrary...\n");
   // If you want to return control to the delay-load helper, return 0.
   // Otherwise, return your own HMODULE to be used by the helper 
   // instead of having it call LoadLibrary itself.
   /*{
    // You can build the DLL path by yourself, and call LoadLibrary 
    // to load the DLL from the path. For simplicity, the sample uses 
    // the dll name to load the DLL, which is the default behavior of 
    // the helper function.           
   }*/
   break;

  case dliNotePreGetProcAddress:
   printf("\tdliNotePreGetProcAddress...\n");
   // If you want to return control to the delay-load helper, return 0. 
   // If you choose you may supply your own FARPROC function address and 
   // bypass the helper's call to GetProcAddress.
   break;
   
  case dliFailLoadLib : 
   printf("\tdliFailLoadLib...\n");
   // LoadLibrary failed.
   // If you don't want to handle this failure yourself, return 0. In 
   // this case the helper will raise an exception (ERROR_MOD_NOT_FOUND) 
   // and exit. If you want to handle the failure by loading an 
   // alternate DLL (for example), then return the HMODULE for the 
   // alternate DLL. The helper will continue execution with this 
   // alternate DLL and attempt to find the requested entrypoint via 
   // GetProcAddress.
   break;
   
  case dliFailGetProc :
   printf("\tdliFailGetProc...\n");
   // GetProcAddress failed.
   // If you don't want to handle this failure yourself, return 0. In 
   // this case the helper will raise an exception (ERROR_PROC_NOT_FOUND) 
   // and exit. If you choose you may handle the failure by returning an 
   // alternate FARPROC function address.
   printf("Failed to get the function %s.\n", pdli->dlp.szProcName);  
   break;
   
  case dliNoteEndProcessing : 
   printf("\tdliNoteEndProcessing...\n");
   // This notification is called after all processing is done. There is 
   // no opportunity for modifying the helper's behavior at this point 
   // except by longjmp()/throw()/RaiseException. No return value is 
   // processed.  
   break;
    }
 
 printf("\tDLL(HMODULE) = %s(0x%08X)\n", pdli->szDll, pdli->hmodCur);
    if (pdli->dlp.fImportByName) {
        printf("\tProc = %s\n", pdli->dlp.szProcName);
    } else {
        printf("\tOrdinal = 0x%08x\n", pdli->dlp.dwOrdinal);
    }

    return NULL;
}

PfnDliHook __pfnDliNotifyHook2 = DelayLoadHook;
PfnDliHook __pfnDliFailureHook2 = DelayLoadHook;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 int nRetCode = 0;
 //CString csTemp = "123";//可開啟看看執行後的畫面

 printf("\n//////////////////////////////////////////////////////////////////////////\n\n");

 return nRetCode;
}
設定Linker的參數


執行畫面


沒有留言:

張貼留言