【问题标题】:Making a singleton application across all users跨所有用户制作单例应用程序
【发布时间】:2014-05-10 09:55:06
【问题描述】:

我正在尝试创建一个仅允许所有 Windows 用户使用单个实例的应用程序。

我目前正在通过打开要写入的文件并将其保持打开状态来做到这一点。这种方法安全吗?您知道使用 C 的替代方法吗?

【问题讨论】:

    标签: c windows winapi single-instance


    【解决方案1】:

    标准解决方案是在应用程序启动期间创建一个全局mutex。第一次启动应用程序时,这将成功。在随后的尝试中,它将失败,这就是您停止并无法加载第二个实例的线索。

    您可以通过调用CreateMutex function 在 Windows 中创建互斥锁。如链接文档所示,在互斥锁名称前加上 Global\ 可确保它对所有终端服务器会话可见,这正是您想要的。相比之下,Local\ 前缀将使其仅对创建它的用户会话可见。

    int WINAPI _tWinMain(...)
    {
       const TCHAR szMutexName[] = TEXT("Global\\UNIQUE_NAME_FOR_YOUR_APP");
       HANDLE hMutex = CreateMutex(NULL,        /* use default security attributes */
                                   TRUE,        /* create an owned mutex           */
                                   szMutexName  /* name of the mutex               */);
       if (GetLastError() == ERROR_ALREADY_EXISTS)
       {
           // The mutex already exists, meaning an instance of the app is already running,
           // either in this user session or another session on the same machine.
           // 
           // Here is where you show an instructive error message to the user,
           // and then bow out gracefully.
           MessageBox(hInstance,
                      TEXT("Another instance of this application is already running."),
                      TEXT("Fatal Error"),
                      MB_OK | MB_ICONERROR);
           CloseHandle(hMutex);
           return 1;
       }
       else
       {
           assert(hMutex != NULL);
    
           // Otherwise, you're the first instance, so you're good to go.
           // Continue loading the application here.
       }
    }
    

    虽然有些人可能认为它是可选的,但由于操作系统会为您处理它,我始终主张在您自己之后明确清理并在您的应用程序退出时调用 ReleaseMutexCloseHandle。这不处理崩溃并且没有机会运行清理代码的情况,但就像我提到的,操作系统将在拥有进程终止后清理任何悬空的互斥锁。

    【讨论】:

    • 我不记得读过那篇博文,但对我来说似乎很明显。我不是单实例应用程序的忠实拥护者,但是如果您要这样做,我想不出更好的方法。 Raymond 关于不要让非管理员阻止其他用户运行该应用程序的建议很好,但我不完全确定如果您想允许非管理员最初启动该应用程序,您将如何实施。我想当管理员启动第二个实例时,您必须编写代码来关闭初始实例?
    • 在这种情况下不要打电话给ReleaseMutex()。请改用CloseHandle()。仅当您获得互斥锁的所有权时才使用ReleaseMutex(),您的代码示例没有这样做(如果CreateMutex() 报告ERROR_ALREADY_EXISTS,则bInitialOwner 参数被忽略)。在这种情况下,bInitialOwner 参数应设置为 FALSE 而不是 TRUE,因为您无需担心所有权,只需担心存在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    相关资源
    最近更新 更多