View Single Post
 
Old 03-28-2006, 07:17 PM
shaul_ahuva shaul_ahuva is offline
Ultimate Contributor

Retired Leader
* Expert *
 
Join Date: Jul 2003
Location: Camp Hill, PA
Posts: 1,992
Default

And another one, this time using a mutex.

Code:
Imports System.Threading ''' <summary> ''' Manages application instances ''' </summary> ''' <remarks></remarks> Public Class InstanceManager ''' <summary> ''' Keeps a reference to the created mutex. ''' </summary> ''' <remarks></remarks> Private Shared CurrentInstance As InstanceInfo #Region "InstanceInfo" ''' <summary> ''' Functions as a wrapper for the application instance mutex. ''' </summary> ''' <remarks>The ApplicationName and MultiUser fields make up the mutex name.</remarks> Private Class InstanceInfo Implements System.IDisposable Private ApplicationName As String Private InstanceMutex As Mutex Private IsDisposed As Boolean Private MultiUser As Boolean ''' <summary> ''' Initializes a new instance of the <see cref="InstanceInfo">InstanceInfo</see> class. ''' </summary> ''' <param name="instanceMutex">The <see cref="System.Threading.Mutex">Mutex</see> used ''' to keep track of application instances.</param> ''' <param name="applicationName">The application name.</param> ''' <param name="multiUser">Indicates if the mutex is local or global.</param> ''' <remarks></remarks> Friend Sub New(ByVal instanceMutex As System.Threading.Mutex, ByVal applicationName As String, _ ByVal multiUser As Boolean) Me.ApplicationName = applicationName Me.InstanceMutex = instanceMutex Me.MultiUser = multiUser GC.KeepAlive(Me) End Sub ''' <summary> ''' Releases the mutex. ''' </summary> ''' <remarks></remarks> Protected Overrides Sub Finalize() Me.Dispose() End Sub ''' <summary> ''' Returns if the specified application mutex is already defined. ''' </summary> ''' <param name="applicationName">The application name.</param> ''' <param name="multiUser">Indicates if the request is for a local or global mutex.</param> ''' <returns></returns> ''' <remarks></remarks> Friend Function HasMutex(ByVal applicationName As String, ByVal multiUser As Boolean) As Boolean Return Me.ApplicationName = applicationName AndAlso Me.MultiUser = multiUser End Function #Region "Dispose" ''' <summary> ''' Disposes of resources. ''' </summary> ''' <remarks></remarks> Public Sub Dispose() Implements IDisposable.Dispose Me.Dispose(True) GC.SuppressFinalize(Me) End Sub ''' <summary> ''' Disposes of resources. ''' </summary> ''' <param name="disposing"></param> ''' <remarks></remarks> Protected Overridable Sub Dispose(ByVal disposing As Boolean) If Not Me.IsDisposed Then If disposing Then End If Me.InstanceMutex.Close() Me.InstanceMutex = Nothing End If Me.IsDisposed = True End Sub #End Region End Class #End Region ''' <summary> ''' Initializes a new instance of the <see cref="InstanceManager">InstanceManager</see> class. ''' </summary> ''' <remarks>Prevent external instantiation.</remarks> Private Sub New() End Sub ''' <summary> ''' Registers the current application instance as the first instance for the local user only. ''' </summary> ''' <returns>Flag indicating if this application instance is the first instance.</returns> ''' <remarks></remarks> Public Shared Function RegisterFirstInstance() As Boolean Return InstanceManager.RegisterFirstInstance(True) End Function ''' <summary> ''' Registers the current application instance as the first instance. ''' </summary> ''' <param name="multiUser">Indicates if the application can be run by more than one user at a time.</param> ''' <returns>Flag indicating if this application instance is the first instance.</returns> ''' <remarks></remarks> Public Shared Function RegisterFirstInstance(ByVal multiUser As Boolean) As Boolean Dim appName As String = Process.GetCurrentProcess().ProcessName If InstanceManager.CurrentInstance Is Nothing OrElse _ Not InstanceManager.CurrentInstance.HasMutex(appName, multiUser) Then Dim first As Boolean = False Dim m As Mutex If Not multiUser Then 'Create the mutex in the global namespace so that only one user can run the app at one time. 'This will throw an exception in additional instances. Use ACLs in .NET 2.0 to mitigate this. Try m = New Mutex(False, "Global\" & appName, first) Catch ex As Exception Return False End Try Else 'Create the mutex in the local namespace so that every logged on user can run the app. m = New Mutex(False, "Local\" & appName, first) End If If first Then 'Get rid of the existing mutex if it exists (different namespace). If Not InstanceManager.CurrentInstance Is Nothing Then InstanceManager.CurrentInstance.Dispose() End If 'Keep the mutex instance around until the shared object is finalized. InstanceManager.CurrentInstance = New InstanceInfo(m, appName, multiUser) Else 'This isn't the first instance. m.Close() Return False End If End If Return True End Function End Class

Usage:
Code:
If Not InstanceManager.RegisterFirstInstance() Then MessageBox.Show("Only one instance can be running for a user at a time!") Application.Exit() End If

This code works in .NET 1.1 and 2.0, and supports previous instance detection for the current user session or the entire system (all user sessions).
Reply With Quote