本文来自MSDN,原文地址:http://support.microsoft.com/kb/164787/zh-cn
Microsoft Windows 95、Windows 98 和 Windows Millennium Edition (Me) 包含两个名为 Rundll.exe 和 Rundll32.exe 的命令行实用程序,通过这两个程序可调用从 16 位或 32 位 DLL 导出的函数。但是,使用 Rundll 和 Rundll32 程序并不能调用从任何 DLL 导出的任何函数。例如,不能使用这两个实用程序调用从系统 DLL 中导出的 Win32 API(应用程序编程接口)调用。这两个程序只允许您调用从 DLL 导出的、明确编写为供这两个程序调用的函数。本文详细介绍了 Rundll 和 Rundll32 程序在上面列出的 Windows 操作系统中的用法。
MIcrosoft Windows NT 4.0、Windows 2000 和 Windows XP 在发行时只附带 Rundll32。这些平台都不提供对 Rundll(Win16 实用程序)的支持。
Rundll 和 Rundll32 实用程序最初设计为仅供 Microsoft 内部使用。但是它们提供的功能非常通用,因此现在可供在一般情况下使用。请注意,Windows NT 4.0 发行时只随附 Rundll32 实用程序,并且只支持 Rundll32。
16 位 DLL:
void FAR PASCAL __loadds EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); 32 位 DLL: void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); 同样,对于 EntryPoint 函数也有三个问题需要注意:很明显,“EntryPoint”名称应该替换为您的入口点函数的实际名称。请注意,Rundll32 的入口点与 32 位 DLL 中的 DllEntryPoint 函数完全无关,后者处理进程和线程的连接/分离通知。Rundll32 的入口点函数必须使用 _stdcall 调用约定定义(CALLBACK 默认情况下使用 _stdcall 属性)。如果缺少 _stdcall 属性,则函数默认使用 _cdecl 调用约定,然后 Rundll32 将在调用该函数后异常终止。由于您必须如上所述使用 _stdcall 调用约定声明该函数,因此如果 DLL 是用 C 语言编写的,Visual C++ 编译器会将该函数实际导出为 _EntryPoint@16;如果 DLL 是用 C++ 语言编写的,则 Visual C++ 编译器将进一步使用名称修饰。所以,请务必在 Rundll 或 Rundll32 的命令行中使用正确导出的名称。如果您想避免使用修饰名称,请使用 .def 文件,并按名称导出入口点函数。在使用 Visual C++ 编译器时,请参考产品文档和以下文章,以了解有关名称修饰的更多信息: 140485(http://support.microsoft.com/kb/140485/ ) 导出 32 位 DLL 中类似 PASCAL 的符号Rundll 入口点的参数如下所示: hwnd - 窗口句柄,它应该用作 DLL 创建的任何窗口的所有者窗口hinst - DLL 的实例句柄 lpszCmdLine - DLL 应分析的 ASCIIZ 命令行nCmdShow - 描述 DLL 的窗口应如何显示 在下面的示例中: RUNDLL.EXE SETUPX.DLL,InstallHinfSection 132 C:\WINDOWS\INF\SHELL.INF Rundll 将调用 Setupx.dll 中的 InstallHinfSection() EntryPoint 函数,并向其传递以下参数: hwnd =(父窗口句柄)hinst = SETUPX.DLL 的 HINSTANCE lpszCmdLine = "132 C:\WINDOWS\INF\SHELL.INF" nCmdShow =(传递给 CreateProcess 的任何 nCmdShow) 请注意,<entrypoint> 函数(在上例中为 InstallHinfSection())必须分析它自己的命令行(上面的 lpszCmdLine 参数),并在必要时使用个别参数。Rundll.exe 最多只分析到传递给它的命令行的可选参数。其余的分析工作则由 <entrypoint> 函数来完成。 有关 Windows 95 和 Windows NT 之间的区别的特别提示在 Windows NT、Windows 2000 和 Windows XP 中,Rundll32.exe 的行为稍有不同,目的是为了适应 UNICODE 命令行。
Windows NT 首先尝试对 <EntryPoint>W 调用 GetProcAddress 以获取其地址。如果找到该入口点,则假定原型为: void CALLBACK EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow); 这与 ANSI EntryPoint 相同,只是 lpszCmdLine 参数现在是一个 UNICODE 字符串。
如果没有找到 <EntryPoint>W 入口点,Windows NT 就会对 <entrypoint>A 和 <entrypoint> 调用 GetProcAddress 以获取其地址。如果发现其中任何一个地址,则将其视为 ANSI 入口点,并像在 Windows 95/98/Me 中那样进行处理。因此,如果希望 DLL 在带 ANSI 支持的 Windows 95 中以及带 UNICODE 支持的 Windows NT/2000/XP 中运行,您应该导出以下两个函数:EntryPointW 和 EntryPoint。在 Windows NT/2000/Me 中,通过 UNICODE 命令行调用 EntryPointW 函数;在 Windows 95/98/Me 中,则通过 ANSI 命令行调用 EntryPoint 函数。 有关 Rundll 的用法的示例,请参考以下有关如何使用 Rundll 命令行实用程序在 Windows 95 中启动“控制面板”小程序的文章: 135068(http://support.microsoft.com/kb/135068/ ) 如何在 Windows 95、98 或 WinNT 中启动“控制面板”小程序