这两者现在表示的是同样的意思,但在以前它们的含义是非常不同的。这个区别主要是来自于16位Windows。

在过去,模块(module)表示一个已被加载到内存的磁盘文件,并且模块句柄指向的是一个描述文件信息的数据结构,这个数据结构所包含的信息是:这些文件来自什么地方,以及被加载到内存的什么位置。而实例(instance)表示的则是一组变量。

我们可以使用一个很形象的比喻:模块就像一个C++类,它描述了如何构造一个对象,以及实现一些方法,并且描述了由这个类创建出来的对象的行为。而实例就像是一个用这个类创建出来的C++对象,它描述的是某个特定对象的状态,而状态也就相当于这个对象中成员的值。

在16位Windows中,所有的程序都是在同一个地址空间中运行的,即时有五个程序使用同一个DLL,这个DLL也只会被加载到内存中一次,并且DLL的数据段也只有一个副本(在C++/C#术语中,DLL就好像是一个单件(singleton)类)。

这是正确的,DLL应该是属于系统范围的,而不是属于进程范围的。对于每个使用DLL的程序,DLL不会单独创建一个独立的数据副本。不过,如果在DLL中需要知道每个程序的一些信息,你必须自己来记录这些信息。

我们用实例句柄来表示一个程序,而不是模块句柄,因为在打开的两个记事本程序中有着相同的模块句柄(因为在每个实例中运行的是相同的代码)。这样,把这两个记事本程序区分开来的东西就是在每个实例中都包含了自己的变量。

这就是为什么在WinExec函数和ShellExecute函数中返回的是HINSTANCE:这是从16位Windows中沿用过来的方式,其中HINSTANCE正式用来标识程序的方法。

在Win32中程序是运行在独立的地址空间中,因此程序的实例句柄无法跨越进程边界。因此设计者们只需要使用唯一一个信息:模块的基地址。在Win32中HINSTANCE和HMODULE都用来表示模块的基地址。