I've written the next code that prevents multi-instancing via MUTEX
, but I would like to extend its funcionality by allowing to set the maximum number of allowed instances, so I should could decide whether I want to allow only a single instance or a multi-instace of only 3 instances (for example).
I've tried to figure out how to count the amount of mutexes of a process, but I didn't find anything about.
By the other hand I've found a lot of posts in StackOverflow explaining how to count the amount of processes by it's filename, I'm not interested in any of this 'cause I've choosed a MUTEX detection which for me is more secure.
Someone could help me in this whim?.
This is all what I have done:
Namespace My
Partial Friend Class MyApplication
#Region " Properties "
''' <summary>
''' Gets the current process mutex identifier.
''' </summary>
''' <value>The current process mutex identifier.</value>
''' <exception cref="System.FormatException">The specified value is not a valid GUID format.</exception>
Private ReadOnly Property MutexID As String
Get
' Define a Golabl Unique Identifier to name the Mutex.
Dim Id As String = "b045ce40-2863-4ce7-a7df-8afca8214454"
If Guid.TryParse(input:=Id, result:=New Guid) Then
Return Id
Else
Throw New FormatException("The specified value is not in a valid GUID format.")
End If
End Get
End Property
''' <summary>
''' Gets the maximum instances allowed for this process.
''' </summary>
''' <value>The maximum instances allowed for this process.</value>
Private ReadOnly Property MaxInstances As Integer
Get
Return 2
End Get
End Property
#End Region
#Region " Private Methods "
''' <summary>
''' Determines whether this is the unique instance that is running for this process.
''' </summary>
''' <returns><c>true</c> if this is the unique instance; otherwise, <c>false</c>.</returns>
Private Function IsUniqueInstance() As Boolean
Dim mtx As Threading.Mutex = Nothing
Try
mtx = Threading.Mutex.OpenExisting(name:=Me.MutexID)
mtx.Close()
mtx = Nothing
Catch
mtx = New Threading.Mutex(initiallyOwned:=True, name:=Me.MutexID)
End Try
Return mtx IsNot Nothing
End Function
#End Region
#Region " Event-Handlers "
''' <summary>
''' This occurs when the application starts, before the startup Form is created.
''' </summary>
''' <param name="sender">The source of the event.</param>
''' <param name="e">The <see cref="ApplicationServices.StartupEventArgs"/> instance containing the event data.</param>
Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As ApplicationServices.StartupEventArgs) _
Handles Me.Startup
' If there is more than one instance running of this process with the same mutex then...
If Not Me.IsUniqueInstance Then ' Prevent multi-instancing.
MessageBox.Show("This is a limited demo, to run multiple instances please purchase the program.",
Application.Info.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error)
' Cancel the application execution.
e.Cancel = True
End If
End Sub
#End Region
End Class ' MyApplication
End Namespace
UPDATE
This is the code that I'm trying, I've tried it in the application events, in the form constructor, in the load and shown event, but the multiinstances are not detected.
Private Sub test() Handles Me.Startup
Using semaphore As New Semaphore(3I, 3I, "something")
If Not semaphore.WaitOne(100I) Then
MsgBox("Already max instances running")
End
Else
MsgBox("test")
End If
End Using
End Sub
Mutex
is for mutual exclusion. It will atmost allow only one thread to proceed. If you need to allow number of threads(process in this case) to proceed you need a Semaphore
rather than mutex.
C# sample:
private static void Main()
{
using (Semaphore semaphore = new Semaphore(3, 3, Assembly.GetExecutingAssembly().GetName().FullName))
{
if (!semaphore.WaitOne(100))
{
MessageBox.Show("Already max instances running");
return;
}
//Start your application here
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
VB.Net sample:
Private Shared Sub Main()
Using semaphore As New Semaphore(3, 3, Assembly.GetExecutingAssembly().GetName().FullName)
If Not semaphore.WaitOne(100) Then
MessageBox.Show("Already max instances running")
Return
End If
'Start your application here
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New Form1())
End Using
End Sub
P.S: Code converted with http://converter.telerik.com/ from C# to VB