程序只启动一个实例的几种方法

来源:互联网 发布:android 和风天气 数据 编辑:程序博客网 时间:2024/05/02 08:54

有些时候,我们要求一个程序在系统中只能启动一个实例。比如,Windows自带的播放软件Windows Medea Player在Windows里就只能启动一个实例。原因很简单,如果同时启动几个实例,却播放不同的文件,那么声音和图像就会引起混乱。在设计模式中,就有一个SINGLETON模式,该模式就是让类只有一个实例。
    对于程序而言,我们只有在程序启动的时候去检测某个设置,如果程序没有启动,就把设置更新为程序已经启动,然后正常启动程序;如果程序已经启动,那么就终止程序的启动。在程序退出的时候把设置恢复为程序没有启动。按照上面的思路,我们很容易就能想出下面的两种方法:
    一,文件法
    在硬盘上创建一个文件,在文件里设置一个值,根据这个值来判断程序是否已经启动。这种方法也是可以设置同时打开多个进程。

比如最多打开五个,然后你那边有个数字相对应,以及有个当前已打开的个数的计数器,然后打开一个计数器就加一,而退出一个计数器就减一。
    二,注册表法
    在注册表中创建一个键,根据该键的键值来决定是否要启动程序。
    但是,上面的两种方法,都有I/O操作。我觉得这不是最好的方法。下面就介绍两种不用I/O操作的方法。思路跟上面是一样的,在进程启动的时候去检测某个设置是否继续启动进程。由于要判断同一个程序是否已经启动一个实例,也就是说会有两个进程去访问同一个设置,所以该设置应该是可以夸进程访问的,比如上面两种方法中的文件和注册表。我们在用VC进行开发时,还可以用文件映射和互斥量。下面是详细的说明:
    VC在创建工程的时候,会自动创建一个App的类。比如,你的工程名是StarLee,那么这个App类的类名就是CStarLeeApp。在进程启动和退出的时候会分别调用该类的两个方法:InitInstance()和ExitInstance()。所以,我们的代码都是添加在这两个方法里面的。
    三,文件映射法
    首先,给App类加上一个成员变量:

HANDLE m_hMap;

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

m_hMap = CreateFileMapping(NULL, NULL, PAGE_READONLY, 0, 13, "StarLee");

// 检测是否已经创建FileMapping
// 如果已经创建,就终止进程的启动
if ((m_hMap!= NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
{
     CloseHandle(m_hMap);
    
     MessageBox(NULL,
"该进程已经启动", "错误", MB_OK);

    
return FALSE;
}

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

if (m_hMap!= NULL)
     CloseHandle(m_hMap);

    四,互斥量法
    首先,给App类加上一个成员变量:

HANDLE m_hMutex;

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

m_hMutex = CreateMutex(NULL, TRUE, "StarLee");

// 检测是否已经创建Mutex
// 如果已经创建,就终止进程的启动
if ((m_hMutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
{
     ReleaseMutex(m_hMutex);

     MessageBox(NULL,
"该进程已经启动", "错误", MB_OK);

    
return FALSE;
}

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

if (m_hMutex != NULL)
{
     ReleaseMutex(m_hMutex);
     CloseHandle(m_hMutex);
}

    上面两种方法的思路和代码添加的步骤都是一样的,当然效果也一样,选择任何一种方法都能达到让进程只启动一个实例的目的。

 

五:进程共享变量----#pragma data_seg用法

详情可以看http://blog.csdn.net/aidy22/archive/2009/08/17/4454647.aspx

 

这个是可以控制打开的进程个数,例如最多可以开两个啊,比如游戏《浪漫庄园》。

希望以上可以对大家有所帮助