/**************************************dll.h****************************************/
#ifndef LIB_H
#define LIB_H
extern "C" void CALLBACK test(HWND hwnd,HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
#endif
/**************************************dll.def****************************************/
LIBRARY Dll
EXPORTS
test @ 4
/**************************************dll.cpp****************************************/
#include "windows.h"
#include "stdio.h"
BOOL APIENTRY DllMain( HANDLE hModule,
/*
进程中的每个DLL模块被全局唯一的32字节的HINSTANCE句柄标识进程自己还有一个HINSTANCE句柄。
所有这些模块句柄都只有在特定的进程内部有效,它们代表了DLL或EXE模块在进程虚拟空间中的起始
地址。在Win32中,HINSTANCE和HMODULE的值是相同的,这两种类型可以替换使用。进程模块句柄几乎
总是等于0x400000,而DLL模块的加载地址的缺省句柄是0x10000000。如果程序同时使用了几个DLL模
块,每一个都会有不同的HINSTANCE值。这是因为在创建DLL文件时指定了不同的基地址,或者是因为
加载程序对DLL代码进行了重定位。
*/
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL,"DLL 开始加载。。","消息",MB_OK|MB_ICONASTERISK);
break;
case DLL_THREAD_ATTACH:
//MessageBox(NULL,"DLL_THREAD_ATTACH - 2","错误",MB_OK|MB_ICONASTERISK);
break;
case DLL_THREAD_DETACH:
//MessageBox(NULL,"DLL_THREAD_DETACH - 3","错误",MB_OK|MB_ICONASTERISK);
break;
case DLL_PROCESS_DETACH:
//MessageBox(NULL,"DLL 退出","错误",MB_OK|MB_ICONERROR);
break;
}
return TRUE;
}
void CALLBACK test(HWND hwnd,HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
char sztemp[255];
GetModuleFileName(hinst,sztemp,sizeof(sztemp));
MessageBox (NULL,sztemp,"调用程序是:",MB_OK|MB_ICONASTERISK);
MessageBox (NULL,lpszCmdLine,"传入的参数是:",MB_OK|MB_ICONASTERISK);
/*
RUNDLL32.EXE是如何装载DLL并调用其中函数的?
一、操作系统
Windows 95/98/ME提供rundll.exe和rundll32.exe,前者用来处理16位的DLL,后者用来处理32位的DLL,而NT/2000/XP/2003则只提供rundll32.exe。除此之外,两个程序的行为没什么不同。
二、命令行格式
RUNDLL32.EXE <DLL名>,<函数名> <可选的参数>
例如:RUNDLL32.EXE MyDll.DLL,TheFunction Hello World
则RUNDLL32会装载名为MyDLL.DLL的动态链接库,并调用动态链接库中的函数TheFunction,向它传递参数’Hello World’
三、注意事项
1、如果没有指名DLL的路径全名,那么RUNDLL32按以下顺序搜索DLL:
a、RUNDLL32所在的目录
b、当前目录
c、系统目录(98通常为WINDOWS安装目录下面的SYSTEM目录、NT和2000通常为WINDOWS安装目录下面的SYSTEM32目录)
d、如果是NT和2000系统,搜索16位系统目录,即WINDOWS安装目录下面的SYSTEM目录
e、WINDOWS安装目录
f、PATH环境变量中指明的搜索路径
2、建议使用DLL的全路径名,但推荐用短文件名,因为RUNDLL32无法识别路径全名中包含的空格。
3、DLL文件名中不能包含空格、逗号和引号。
4、DLL名和函数名之间必须有一个逗号(,),且逗号前后不能有空格。
四、RUNDLL32如何工作
RUNDLL32按以下步骤工作:
1、分析命令行
2、用LoadLibrary()这个API来装载DLL
3、用GetProcAddress()这个API来找到函数入口点
4、调用函数,把<可选参数>做为命令行传递给函数
5. 函数返回后,用FreeLibrary()来卸掉DLL
6、结束RUNDLL32程序的运行
五、如何编写DLL中的函数
DLL中的函数应该这样写(不考虑16位DLL):
C语言: void CALLBACK TheFunction(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
PASCAL:procedure TheFunction(AWnd, AInst: THandle; ACmdLine: PChar; ACmdShow: Integer); stdcall;
请注意:函数的调用约定必须是stdcall,否则RUNDLL32可能会出错。
六、示例
RUNDLL32.EXE MyDll.DLL,TheFunction Hello World
则TheFunction收到的参数如下:
AWnd: 父窗口句柄
AInst: MyDLL.DLL的句柄
ACmdLine:字符串(以零结尾)’Hello World’
ACmdShow:如何显示窗口
七、UNICODE系统
从NT开始的WINDOWS都是基于UNICODE的,因为,在这样的环境下,RUNDLL32首先尝试在函数名后面加个W,如果没找到这个函数,就尝试在函数名后面加A,如果还没有找到,再用提供的函数名。如果添加W字符后找到函数,则lpszCmdLine传递的是宽字符串。
*/
}