如何查找给定的应用程序是否是单个实例?

时间:2011-06-29 05:25:52

标签: c++ windows process createprocess single-instance

我正在寻找一种有效的方法来查找给定的应用程序(比如app.exe)是否是单个实例?我想到了以下这些解决方案:

  1. 执行两次CreateProcess()并检查该应用程序是否有两个或更多实例运行?如果不是,则为单实例应用程序。但是,这效率不高。
  2. 执行CreateProcess()并等待1-2秒。如果此实例被终止(因为已经有一个实例正在运行),它将是单实例应用程序。
  3. 但我不相信上述两种解决方案。在Windows中还有其他有效的方法吗?

    请注意,我不会杀死或对该应用程序的已运行(如果有)实例进行任何修改。

6 个答案:

答案 0 :(得分:7)

从另一个角度考虑:编写程序时,如何指定它是单实例还是多实例?是否有一种方法可以让其他程序在不运行程序的情况下从程序中获取该信息? (一旦你回答了这个问题,那么你就得到了问题的答案。)

这个问题通常无法解决,因为单实例/多实例在运行时确定并且可以基于运行时条件。例如,某些应用程序“有时是多个实例,有时是单个”:如果运行应用程序打开文档X,然后生成文档Y,则将获得两个实例。但是,如果您打开文档X,然后再次打开文档X,这两个实例将折叠成一个。其他应用程序可能具有配置开关,您可以选择它们是单实例还是多实例。或者也许他们决定翻转硬币,如果是尾部则决定单个实例,如果是头部则决定是多个实例。

答案 1 :(得分:1)

最好的方法是使用名为Mutex(互斥)的同步对象。你可以谷歌吧。 我认为以下代码可能有所帮助。

//---------------------------------------------------------------------------
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    try
    {
        HANDLE hMutex=OpenMutex(MUTEX_ALL_ACCESS,0,"SIns");
        if (!hMutex) {
            //Mutex doesn’t exist. This is the first instance so create the mutex.
            //in this case app name is SIns (Single Instance)
            hMutex=CreateMutex(0,0,"SIns");
            Application->Initialize();
            Application->MainFormOnTaskBar = true;
            Application->CreateForm(__classid(TfMain), &fMain);
            Application->Run();
            ReleaseMutex(hMutex);
        }
        else{
            //This is not single. The prev instance is already running 
            //so informing about it 
            //remember that if it finds prev instance we're activating it here
            //you may do whatsoever here ...... e.g. you may kill process or stuff like this:)
            ShowMessage("The program is already running. Switching to ...");
            HWND hWnd=FindWindow(0,"SIns");
            SetForegroundWindow(hWnd);
        }

    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    catch (...)
    {
        try
        {
            throw Exception("");
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
    }
    return 0;
}
//---------------------------------------------------------------------------

答案 2 :(得分:1)

根本无法做到这一点。如果应用程序检查互斥锁,然后使消息框告诉用户实例已在运行,并且只有当用户解除它时会发生什么情况才会终止应用程序?有许多不同的方法可以通过一些共享资源,互斥,共享文件来确保互斥,甚至可能设置一些注册表项,方法是无限的。

答案 3 :(得分:0)

通常的解决方案是使用某种锁定文件。下 例如,传统的Unix应用程序将通过创建一个 文件(即使文件存在也会成功),然后尝试创建一个 链接到它(原子动作);如果失败,应用程序将 立即自杀。在Windows下,CreateFile的共享模式 可以用于相同的效果:打开共享模式0的文件,如果 失败了,退出了。 (如果进程,Unix解决方案将保留锁定 崩溃,需要手动清理。 Windows解决方案 如果系统崩溃,将删除锁。)

答案 4 :(得分:0)

您可以使用互斥锁...我使用以下代码进行检查:

bool insureApplicationUniqueness(HANDLE& mutexHandle)
{
    mutexHandle=CreateMutexW(NULL,true,UNIQUE_INSTANCE_MUTEX_NAME);
    if( mutexHandle&&(ERROR_ALREADY_EXISTS==GetLastError()))
    {
        CloseHandle(mutexHandle);
        return false;
    }
    return true;
}

但这适用于哪些源代码属于您的应用程序以及哪些检查是自身运行的另一个实例。

答案 5 :(得分:0)

概念的问题在于,在常见环境中,没有明确的静态数据来确定应用程序是否是单实例。您只能继续行为,但无法完全测试行为。

如果您的应用程序是多实例但无法打开已打开的文件,该怎么办?如果使用相同的有效文件名对其进行两次测试,则只会创建一个进程,但任何其他命令行参数都会导致存在两个进程。这是一个单实例程序吗?

你甚至可以说“单一实例”并不是一个定义明确的程序目录。