ElektroStudios
ElektroStudios

Reputation: 20464

Determine if there is more than one instance of the same process running?

I rescued this VB6-stylized snippet with intention to refactor/update but then I discovered it is not working as expected.

The code is supposed to easy determine at any time whether there is more than one instance of the same process running:

Public Declare Function CreateMutexA Lib "Kernel32.dll" (
        ByVal lpSecurityAttributes As Integer,
        ByVal bInitialOwner As Boolean,
        ByVal lpName As String) As Integer

Public Declare Function GetLastError Lib "Kernel32.dll" () As Integer

Public Function My_Application_Is_Already_Running() As Boolean

    ' Attempt to create defualt mutex owned by process
    CreateMutexA(0, True, Process.GetCurrentProcess().MainModule.ModuleName.ToString)
    Return (GetLastError() = 183) ' 183 = ERROR_ALREADY_EXISTS

End Function

If I have only one instance running then it returns False, and if I launch two instances of the same process then the function returns True as expected, the problem is that when one of those instances are closed/gone, the function stills return True.

How I could fix the code above or do this using a proper approach?.

My intention is to have a suitable helper function safe to be called at any moment from whatever app, don't hardcoding a semaphore/mutex algorithm that will work only for one specific project under some specific circunstances etc... the function should be an abstraction to avoid doing anything more than calling the function to get a result, just like the function above (wrongly)does.


Update

I have tried this:

Public NotInheritable Class AppUtil

        Private Shared created As Boolean = False
        Private Shared waitHandle As New EventWaitHandle(initialState:=False,
                                                         mode:=EventResetMode.ManualReset,
                                                         name:="AppUtil#IsRunningAnyOtherInstance",
                                                         createdNew:=created)

        Public Shared Function IsRunningAnyOtherInstance() As Boolean

                Return Not created

        End Function

End Class

In the event-handler of a button in a Form, I have this call:

MsgBox(AppUtil.IsRunningAnyOtherInstance)

After I compile the solution, I launch two instances of the app, the first instance returns False and the newer instance returns True. Both should return True because there are 2 instances open and when closing one of the forms it should return False (because there is only remaining one instance open).

PS: Take into account that the AppUtil class is not instanceable.

Upvotes: 1

Views: 1623

Answers (3)

gd73
gd73

Reputation: 635

Easiest way in my opinion is by using the Mutex class:

        bool isFirstInstance = false;
        Mutex mutex = new Mutex(true, "MyUniqueAppKeyOrGuid", out isFirstInstance);

The first instance will have variable isFirstInstance set to true - all next instances will have it set to false.

Upvotes: 1

MaYaN
MaYaN

Reputation: 6996

There are many ways of achieving this, in C# you could use a Mutex, Semaphore or even Windows Events, something like:

private static EventWaitHandle _handle;

bool created ;
_handle = new EventWaitHandle (false, EventResetMode.ManualReset, "my program#startup", out created) ;
if (created)
{
    StartApp();
}
else 
{
    Exit();
}

More info HERE.

Another approach would be something like:

  string procName = Process.GetCurrentProcess().ProcessName;
  if (Process.GetProcessesByName(procName).Length == 1)
  {
      // do whatever //
  }

Upvotes: 1

David Wilson
David Wilson

Reputation: 4439

It's a lot easier nowadays.

This returns the number of processes called "svchost" to the console - you can figure the reset out eh? :0)

Please note that the name you search for has no extension. Also - It returns the results of all processes from all users.

Console.WriteLine(Process.GetProcessesByName("svchost").Count)

Upvotes: 1

Related Questions