2

I'm trying to create an application which only allows a single instance across all Windows users.

I'm currently doing it by opening a file to write and leaving it open. Is this method safe? Do you know of an alternative method using C?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Helio Santos
  • 6,606
  • 3
  • 25
  • 31

1 Answers1

5

The standard solution is to create a global mutex during application startup. The first time that the app is started, this will succeed. On subsequent attempts, it will fail, and that is your clue to halt and fail to load the second instance.

You create mutexes in Windows by calling the CreateMutex function. As the linked documentation indicates, prefixing the name of the mutex with Global\ ensures that it will be visible for all terminal server sessions, which is what you want. By contrast, the Local\ prefix would make it visible only for the user session in which it was created.

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.
   }
}

Although some may argue it is optional, since the OS will handle it for you, I always advocate explicitly cleaning up after yourself and calling ReleaseMutex and CloseHandle when your application is exiting. This doesn't handle the case where you crash and don't have a chance to run your cleanup code, but like I mentioned, the OS will clean up any dangling mutexes after the owning process terminates.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • I don't recall having read that blog post, but it seems rather obvious to me. I'm not a big fan of single instance applications, but if you're going to do it, I can't think of a better way. Raymond's advice about not letting non-administrators prevent other users from running the app is good, but I'm not entirely sure how you'd implement that if you wanted to allow non-admins to start the app initially. I guess you'd have to write code to bump off the initial instance when a second instance is started by an admin? – Cody Gray - on strike May 10 '14 at 11:11
  • Don't call `ReleaseMutex()` in this context. Use `CloseHandle()` instead. Use `ReleaseMutex()` only when you have obtained ownership of the mutex's lock, which your code example is not doing (if `CreateMutex()` reports `ERROR_ALREADY_EXISTS` then the `bInitialOwner` parameter was ignored). In this situation, the `bInitialOwner` parameter should be set to FALSE instead of TRUE since you don't need to worry about ownership, only existence. – Remy Lebeau May 10 '14 at 21:54