为什么WinMain和wWinMain中存在prevInstance参数,即使它总是NULL?

11
由于我是一名初学者,这可能是一个非常基本的问题。 我正在开始使用DirectX 11,在创建我的第一个应用程序时,使用了wWinMain,当在查找WinMain和wWinMain之间的差异时,我遇到了这个参数prevInstance。
根据MSDN,prevInstance始终为null,既然它总是为null,为什么它还存在(因为认为创建者不会提供无用的参数很合理)。并且(引用自书中):
如果需要确定应用程序的先前实例是否已在运行,请使用CreateMutex创建具有唯一名称的mutex。尽管将创建mutex,但CreateMutex函数将返回ERROR_ALREADY_EXISTS。
什么是mutex,以及如何使用它(一个好的链接就足够了)。看起来需要一种方法来查找另一个应用程序实例是否存在,prevInstance应该具有指向它的指针或引用,显然不是这种情况,因为它为null。为什么会这样,prevInstance的作用是什么?

4
仅仅因为它现在总是空并不意味着它过去总是空... - flight
2个回答

19

Raymond Chen的博客 几乎完全致力于讨论Windows API中对我们今天来说是“怪异”的方面。幸运的是,他有一篇博文回答了这个确切的问题:

在16位Windows中,有一个叫做GetInstanceData的函数。该函数接受HINSTANCE、指针和长度,并将该实例的内存复制到当前实例中。(它在某种程度上相当于ReadProcessMemory的16位版本,但限制是第二个和第三个参数必须相同。)

...

这就是WinMain中hPrevInstance参数的原因。如果hPrevInstance不为NULL,则它是已经运行的程序副本的实例句柄。您可以使用GetInstanceData从其中复制数据,更快地启动自己。例如,您可能希望从前一个实例中复制主窗口句柄,以便与其进行通信。

无论hPrevInstance是否为NULL,都告诉您是否是该程序的第一个副本。在16位Windows下,只有程序的第一个实例注册了其类;第二个及随后的实例继续使用由第一个实例注册的类。 (实际上,如果它们尝试,则注册将失败,因为该类已经存在。)因此,所有16位Windows程序都跳过类注册,如果hPrevInstance不为NULL。

设计Win32的人在移植WinMain时遇到了一些问题:该传递什么作为hPrevInstance?毕竟,在Win32中不存在整个模块/实例的概念,并且单独的地址空间意味着第二个实例跳过重新初始化后,程序将不再工作。因此,Win32始终传递NULL,使所有程序都认为自己是第一个实例。

当然,现在对于Windows API来说,除了兼容性原因外,hPrevInstance已经不再相关。MSDN建议您使用互斥锁来检测应用程序的先前实例。
互斥锁代表“互斥排斥”。您可以参考MSDN文档中的CreateMutex()。有很多使用互斥锁来检测应用程序的先前实例的示例,例如这个。基本思路是创建一个带有唯一名称的互斥锁,然后尝试创建该命名互斥锁。如果CreateMutex()返回ERROR_ALREADY_EXISTS,则说明您的应用程序的一个实例已经运行。

5
我擅自总结了博客文章,这样你的回答就不仅仅是一个链接了。 - Jon Purdy
1
@Jon Purdy:非常感谢您的编辑,但是我已经在引用陈先生的整个解释,以免失去上下文。 :-) - In silico
3
结果好就算万事大吉,我想。也许 Stack Overflow 应该有一个指示器来显示正在被编辑的答案。 - Jon Purdy
3
Raymond Chen的博客可能是“为什么在Windows中X会是一种奇怪和奇特的方式”的最佳来源,其中X是某些奇怪和奇特的东西。许多历史上的怪异现象都在那里得到了解释,其中有很多值得阅读的内容。 - Thanatos
1
一种优雅的说法是PrevInstance是一个累赘。 - Laurie Stearn
显示剩余2条评论

2

prev实例参数是为了与16位Windows兼容而存在的。我认为在WinMain的MSDN参考文档中已经说明了,至少曾经有过。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接