2

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

  1. 执行两次 CreateProcess() 并检查该应用程序是否有两个或多个实例正在运行?如果否,则为单实例应用程序。但是,这效率不高。
  2. 执行 CreateProcess() 并等待 1-2 秒。如果这个实例被杀死(因为已经有一个实例为它运行),它将是单实例应用程序。

但我不相信上述两种溶胶。在 Windows 中还有其他有效的方法吗?

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

4

6 回答 6

7

换个角度想:写程序的时候,怎么指定是单实例还是多实例?有没有其他程序可以在不运行程序的情况下从您的程序中获取该信息的方法?(一旦你回答了这个问题,那么你就有了问题的答案。)

这个问题一般是无法解决的,因为单实例/多实例是在运行时确定的,并且可以基于运行时条件。例如,某些应用程序是“有时是多个实例,有时是单个实例”:如果您运行应用程序打开文档 X,然后打开文档 Y,您将获得两个实例。但是,如果您打开文档 X,然后再次打开文档 X,这两个实例将合二为一。其他应用程序可能有一个配置开关,可让您选择它们​​是单实例还是多实例。或者也许他们决定抛硬币,如果是反面,则决定为单实例,如果是正面,则决定为多实例。

于 2011-11-12T15:37:46.090 回答
1

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

于 2011-11-12T15:35:07.307 回答
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;
}
//---------------------------------------------------------------------------
于 2011-11-12T15:17:57.073 回答
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;
}

但这是针对应用程序,哪个源代码是你的,哪个检查是它自己运行的另一个实例。

于 2011-06-29T07:34:08.840 回答
0

这个概念的问题在于,在普通环境中,没有明确的静态数据来确定应用程序是否为单实例。你只有行为要继续,但你不能完全测试行为。

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

由于这个原因,您甚至可以争辩说“单实例”不是一个明确定义的程序类别。

于 2011-06-29T19:45:56.203 回答
0

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

于 2011-06-29T07:32:19.353 回答