您的位置:首页 > 其它

《程序只启动一个实例的几种方法》一文的补充

2007-03-27 09:21 337 查看
我那篇《程序只启动一个实例的几种方法》发表后被推荐到了CSDN首页,有不少网友看了之后提出了一些很好的建议。其中有个网友说可以用共享变量法,我上网收集了一些资料,又经过代码测试,现在补充一下这种方法:
五,共享变量法
首先,在App类的cpp文件开头加上下面的代码:

#pragma data_seg("StarLee") // 自己定义的数据段
char nInstanceCount = -1; // 实例个数,下文会详细用char来定义实例个数的好处
#pragma data_seg()
#pragma comment(linker, "/section:StarLee,rws") // 共享该数据段(r - read, w - write, s - share)

然后,在App类的InitInstance()方法的最前面加上下面的代码:

nInstanceCount++;
if (nInstanceCount > 0)
{
MessageBox(NULL, "该进程已经启动", "错误", MB_OK);

return FALSE;
}

最后,在App类的ExitInstance()方法里加上下面的代码:

nInstanceCount--;

PS:这里介绍一下上面代码中用把实例个数的类型定义为char的小技巧。我们知道char的长度为1个字节,是用-128~127之间的整型来表示的。而我们进程实例的最大值是1,而且在程序的数据段里添加的东西越少越好,所以char就成了最佳之选。

在那篇《程序只启动一个实例的几种方法》的十几个回复中,很多网友都提到了如果进程被意外终止,恢复设置的代码将不会被调用,那样程序就不能再被启动了。为此我针对每种方法都做了测试,下面对结果进行一下分析:
测试环境:
Windows 2000,VC++ 6.0
测试方法:
1,启动程序,在任务管理器终止该进程,再次启动进程。
2,删除App类的ExitInstance()方法里面添加的代码,编译通过以后,启动程序,关闭程序,再次启动程序。
结果:
对于方法一和方法二(文件法和注册表法),由于有I/O操作,如果恢复设置的代码不被调用,除非手动将设置恢复,否则程序就永远不能再被启动。这也是我不推荐这两种方法的主要原因。
对于后3种方法(文件映射法,互斥量法和共享变量法),就算进程被异常终止,恢复设置的代码不被调用,也不会影响程序的再次启动。我觉得,这是因为这3种使用的对象(文件映射,互斥量,共享变量)虽然可以夸进程访问,但是他们还是属于创建者进程的,会随着创建者的销毁而销毁,Windows会在进程结束(无论是正常还是意外)的时候释放它们。
另外,我在MSDN对CreateMutex的介绍中发现了下面这句话:
The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed.
可以说这是明确的告诉我们互斥量在程序终止的时候会被自动释放。
所以,在我介绍的这些让进程只启动一个实例的五种方法中,互斥量法是最好的解决方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: