dlutyuanhongl(乱石铺街)的BLOG

VC知识库BLOG 首页 新随笔 联系 聚合 登录
  11 Posts :: 1 Stories :: 72 Comments :: 2 Trackbacks

留言簿(8)

随笔分类

随笔档案

文章分类

文章档案

相册

搜索

最新评论

阅读排行榜

评论排行榜

    延迟加载的D L L是个隐含链接的D L L,它实际上要等到你的代码试图引用
D L L中包含的一个符号时才进行加载。延迟加载的D L L在下列情况下是非常有用的:
    • 如果你的应用程序使用若干个D L L,那么它的初始化时间就比较长,因为加载程序要将所有需要的D L L映射到进程的地址空间中。解决这个问题的方法之一是在进程运行的时候分开加载各个D L L。延迟加载的D L L能够更容易地完成这样的加载。
    • 如果调用代码中的一个新函数,然后试图在老版本的系统上运行你的应用程序,而该系统中没有该函数,那么加载程序就会报告一个错误,并且不允许该应用程序运行。你需要一种方法让你的应用程序运行,然后,如果(在运行时)发现该应用程序在老的系统上运行,那么你将不调用遗漏的函数。例如,一个应用程序在Windows 2000上运行时想要使用P S A P I函数,而在Windows 98上运行想要使用To o l H e l p函数(比如P r o c e s s 3 2 N e x t)。当该应用程序初始化时,它调用G e t Ve r s i o n E x函数来确定主操作系统,并正确地调用相应的其他函数。如果试图在Windows 98上运行该应用程序,就会导致加载程序显示一条错误消息,因为Windows 98上并不存在P S A P I . d l l模块。同样,延迟加载的D L L能够使你非常容易地解决这个问题。
                                  ------摘自<<Windows核心编程>>
    下面我以简单的代码来展示延迟加载DLL的实现.
  

#include <TlHelp32.h>
#include 
<shlwapi.h>
#pragma comment(lib, 
"shlwapi.lib")

#include 
<delayimp.h>
 // 这个链接开关告诉链接程序将一个特殊的函数--delayLoadHelper嵌入到
 // 你的可执行模块。
#pragma comment(lib, 
"delayimp.lib")

// 延迟加载
#pragma comment(linker, "/Delayload:"shlwapi.dll"")

// 允许卸载DLL
 // __FUnloadDelayLoadedDLL(_T("shlwapi.dll"));可以用此函数将你加载
 // 的DLL卸载掉
 // D e l a y : u n l o a d链接程序开关告诉链接程序将另一个节放入文
 // 件中。该节包含了你清除已经调用的函数时需要的信息,这样它们就可以
 // 再次调用- - d e l a y L o a d H e l p e r函数。当调用
 // - -F U n l o a d D e l a y L o a d e d D l l时,你将想要卸载的延
 // 迟加载的D L L的名字传递给它。该函数进入文件中的未卸载节,并清除
 // D L L的所有函数地址,然后
 // - - F U n l o a d D e l a y L o a d e d D l l调用
 // F r e e L i b r a r y,以便卸载该D L L。
#pragma comment(linker, "/Delay:unload")

void IsModuleLoaded(TCHAR * pszModuleName)
{
    HMODULE hModule 
= GetModuleHandle(pszModuleName);

    TCHAR szName[MAX_PATH] 
= {0};
    _stprintf(szName,
              _T(
"Module "%s" is %sloaded."),
              pszModuleName,
              (hModule 
== NULL) ? _T("not ") : _T(""));
    ::MessageBox(NULL,
                 szName,
                 _T(
"提示"),
                 MB_OK);
}


void GetProcessID(LPTSTR pszProcessName, DWORD& th32ProcessID)
{
    HANDLE hSnapshot 
= NULL;
                       
    __try
    
{
        hSnapshot 
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        
if (INVALID_HANDLE_VALUE == hSnapshot)
       
{
            __leave;
        }


        PROCESSENTRY32 pe;
        ZeroMemory(
&pe, sizeof(PROCESSENTRY32));
        pe.dwSize 
= sizeof(PROCESSENTRY32);

        BOOL bProcess 
= Process32First(hSnapshot, &pe);
        
while (bProcess)
        
{
            
if (pe.szExeFile == StrStrI   
                  (pe.szExeFile, pszProcessName))
            
{
                th32ProcessID 
= pe.th32ProcessID;
                
break;
            }


            bProcess 
= Process32Next(hSnapshot, &pe);
        }


        
if (!bProcess)
        
{
            __leave;
        }

    }

    __finally
    
{
        
if (INVALID_HANDLE_VALUE != hSnapshot)
        
{
            CloseHandle(hSnapshot);
        }

    }

}

用如下代码测试即可
  
    IsModuleLoaded(_T("shlwapi"));
    DWORD dwProcessID;
    GetProcessID(_T(
"csrss.exe"
), dwProcessID);
    std::cout 
<< dwProcessID <<
 std::endl;
    IsModuleLoaded(_T(
"shlwapi"));
 
当程序初始化时并未将DLL映射到进程的地址空间,直到调用函数GetProcessID时,由于其中要导出shlwapi.dll的函数StrStrI,此时该DLL被加载,并且一直存在于进程的地址空间中。
posted on 2005-03-16 21:04 乱石铺街 阅读(3093) 评论(1)  编辑 收藏

Feedback

# 延迟加载DLL———VC 6.0的出色特性 [TrackBack] 2006-09-11 13:49 yaosan
延迟加载DLL———VC 6.0的出色特性
yaosan引用了该文章,地址:http://blog.csdn.net/yaosan/archive/2006/09/11/1207761.aspx

标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]