How to block running two instances of the same program?

后端 未结 8 1254
暗喜
暗喜 2020-12-01 05:23

I need to make sure that user can run only one instance of my program at a time.
Which means, that I have to check programatically, whether the same program is already r

相关标签:
8条回答
  • 2020-12-01 06:03

    I don't have a good solution, but two thoughts:

    1. You could add a ping capability to query the other process and make sure it's not an unrelated process. Firefox does something similar on Linux and doesn't start a new instance when one is already running.

    2. If you use a signal handler, you can ensure the pid file is deleted on all but a kill -9

    0 讨论(0)
  • 2020-12-01 06:07

    There are several methods you can use to accomplish only allowing one instance of your application:

    Method 1: Global synchronization object or memory

    It's usually done by creating a named global mutex or event. If it is already created, then you know the program is already running.

    For example in windows you could do:

        #define APPLICATION_INSTANCE_MUTEX_NAME "{BA49C45E-B29A-4359-A07C-51B65B5571AD}"
    
        //Make sure at most one instance of the tool is running
        HANDLE hMutexOneInstance(::CreateMutex( NULL, TRUE, APPLICATION_INSTANCE_MUTEX_NAME));
        bool bAlreadyRunning((::GetLastError() == ERROR_ALREADY_EXISTS));
        if (hMutexOneInstance == NULL || bAlreadyRunning)
        {
            if(hMutexOneInstance)
            {
                ::ReleaseMutex(hMutexOneInstance);
                ::CloseHandle(hMutexOneInstance);
            }
            throw std::exception("The application is already running");
        }
    

    Method 2: Locking a file, second program can't open the file, so it's open

    You could also exclusively open a file by locking it on application open. If the file is already exclusively opened, and your application cannot receive a file handle, then that means the program is already running. On windows you'd simply not specify sharing flags FILE_SHARE_WRITE on the file you're opening with CreateFile API. On linux you'd use flock.

    Method 3: Search for process name:

    You could enumerate the active processes and search for one with your process name.

    0 讨论(0)
  • 2020-12-01 06:08

    Your method of writing the process pid to a file is a common one that is used in many different established applications. In fact, if you look in your /var/run directory right now I bet you'll find several *.pid files already.

    As you say, it's not 100% robust because there is chance of the pids getting confused. I have heard of programs using flock() to lock an application-specific file that will automatically be unlocked by the OS when the process exits, but this method is more platform-specific and less transparent.

    0 讨论(0)
  • 2020-12-01 06:14

    If you want something that's bog standard, then using a file as a 'lock' is pretty much the way to go. It does have the drawback that you mentioned (if your app doesn't clean up, restarting can be an issue).

    This method is used by quite a few applications, but the only one I can recall off the top of my head is VMware. And yes, there are times when you have to go in and delete the '*.lck' when things get wedged.

    Using a global mutex or other system object as mentioned by Brian Bondy is a better way to go, but these are platform specific, (unless you use some other library to abstract the platform specifics away).

    0 讨论(0)
  • 2020-12-01 06:16

    I scan the process list looking for the name of my apps executable with matching command line parameters then exit if there is a match.

    My app can run more than once, but I don't want it running the same config file at the same time.

    Obviously, this is Windows specific, but the same concept is pretty easy on any *NIX system even without specific libraries simply by opening the shell command 'ps -ef' or a variation and looking for your app.

       '*************************************************************************
       '     Sub: CheckForProcess()
       '  Author: Ron Savage
       '    Date: 10/31/2007
       '
       ' This routine checks for a running process of this app with the same
       ' command line parameters.
       '*************************************************************************
       Private Function CheckForProcess(ByVal processText As String) As Boolean
          Dim isRunning As Boolean = False
          Dim search As New ManagementObjectSearcher("SELECT * FROM Win32_process")
          Dim info As ManagementObject
          Dim procName As String = ""
          Dim procId As String = ""
          Dim procCommandLine As String = ""
    
          For Each info In search.Get()
             If (IsNothing(info.Properties("Name").Value)) Then procName = "NULL" Else procName = Split(info.Properties("Name").Value.ToString, ".")(0)
             If (IsNothing(info.Properties("ProcessId").Value)) Then procId = "NULL" Else procId = info.Properties("ProcessId").Value.ToString
             If (IsNothing(info.Properties("CommandLine").Value)) Then procCommandLine = "NULL" Else procCommandLine = info.Properties("CommandLine").Value.ToString
    
             If (Not procId.Equals(Me.processId) And procName.Equals(processName) And procCommandLine.Contains(processText)) Then
                isRunning = True
             End If
          Next
    
          Return (isRunning)
       End Function
    
    0 讨论(0)
  • 2020-12-01 06:18

    I found a cross platform way to do this using boost/interprocess/sync/named_mutex. Please refer to this answer https://stackoverflow.com/a/42882353/4806882

    0 讨论(0)
提交回复
热议问题