VC和Delphi程序只运行一个实例的方法
有些时候,我们需要我们的程序只运行一个实例,笔者自己作程序也有这样的情况,于是自已探究一番。忙活一阵后,总算小有收获,不敢独享,在天极发表出来,供大家参考。
既然是从根本上解决问题,对于Windows程序而言,就从WinMain函数入口,这是因为在VC中使用SDK的方式编写程序最透明,并且WinMain是作为VC编译器生成EXE文件的默认入口函数。
WinMain的函数原型:
int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);
在WinMain中一共有四个参数,其中第二参数hPrevInstance是一个HINSTANCE,表示程序运行上一个实例的句柄。根据Msdn的说明,这个参数在Win32系统上总为NULL。不过我们还可以通过使用GreateMutex函数来创建一个唯一命名的互斥对象的方法来检测是否已经存在了另一个实例。
GreateMutex的函数原型:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
第一个参数lpMutexAttributes,指向一个SECURITY_ATTRIBUTES结构的指针,用来决定是否允许子进程继承函数返回的句柄。如果这个参数为NULL(空),则不允许被继承。
第二个参数bInitialOwner,如果这个参数为真并且是由调用者(指调用CreateMutex函数的)创建互斥对象,那么由调用的线程(调用CreateMutex函数的线程)获得最初的拥有权。除此之外,调用的线程都不能获得最初的拥有权。决定是否由调用者创建互斥对象,请看“返回值”(Return Values)小节。
第三个函数lpName,指向用来命名互斥对象的以NULL(空)结尾的字符串,这个名字的字符个数限制在MAX_PATH个数字符内。同时这个名字区分大小写。如果参数lpName为NULL(空),将创建一个没有命名的互斥对象。如果参数lpName所指向的字符串和下列各项之中任意一项匹配:existing event,semaphore,waitable timer,job,or file-mapping object,函数将失败并伴随着调用(尽快)GetLastError函数会返回ERROR_INVALID_HANDLE常数。引发这样的结果是由于为这些互斥对象分配了重复的命名空间(这些能够引起重复的命名空间可以在Msdn中通过搜索CreateMutex查看)。
返回值,如果函数成功,返回值是一个新创建的互斥对象的句柄。如果函数失败,返回值为NULL(空)。如果得到的互斥对象是一个在这个函数之前(指这一次调用CreateMutex函数之前)就被命名了的互斥对象并且存在,那么返回值是已存在对象的句柄,同时(尽快)调用GetLastError函数会返回ERROR_ALREADY_EXISTS。无论如何,当第二个调用者(注1)只有有限的访问权限,CreateMutex将会失败,同时会伴随着使用GetLastError返回ERROR_ACCESS_DENIED,那么调用者应该使用OpenMutex函数(更多的信息大家可以到Msdn中查看,现在这些信息已经足够我们用来保证我们的程序只运行一个实例了)。
现在我确定思路:首先创建一个互斥对象,如果创建成功(CreateMutex返回值不为NULL)并调用GetLastError函数返回ERROR_ALREADY_EXISTS常数,说明当前进程不是应用程序的第一个实例,结束程序的运行。
- 上一篇:使用VC6.0实现窗口的任意分割
- 下一篇:用VC++制作播放AVI视频流的动画按钮