Detecting a Previous Instance

reboot
12-17-2003, 08:44 PM
A class to determine if your application is already running:

Public Class PreviousInstance
Private _running As Boolean 'local

'this property gets set to True if there is a previous instance detected
Public Property isRunning() As Boolean
Get
isRunning = _running
End Get
Set(ByVal Value As Boolean)
_running = Value
End Set
End Property

Public Sub New()
'get the current process
Dim thisProcess As Process = Process.GetCurrentProcess()

'get collection of all processes
Dim allProcesses As Process() = Process.GetProcessesByName(thisProcess.ProcessName)

'loop through running processes
Dim p As Process

For Each p In allProcesses
'ignore this process
If p.Id <> thisProcess.Id Then
'make sure it is running from the exe file
If System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/", "\") _
= thisProcess.MainModule.FileName Then

'there is an instance already running, set our flag True and return
_running = True

Return
End If
End If
Next

'no other instance
_running = False
End Sub
End ClassSample usage:Dim p As New PreviousInstance

If p.isRunning Then
MessageBox.Show("Previous instance detected!")

Return
End If

Mike Rosenblum
03-25-2006, 08:52 AM
Here's another approach that I think also appears to work cleanly:''' <summary>
''' Tests whether an instance of the currently running Application is already running.
''' </summary>
''' <returns>
''' Returns 'True' if an instance of the current Application is already running.
''' </returns>
''' <remarks>
''' No parameters are passed into the function. IsAlreadyRunning() relies
''' on the Process.GetCurrentProcess() to determine if other Applications of the
''' same name and path location are already running.
''' </remarks>
''' <Author> Mike_R on xtremevbtalk.com </Author>
''' <Date> 2006.03.25 </Date>
Public Shared Function IsAlreadyRunning() As Boolean
Dim thisProcess As Process = Process.GetCurrentProcess
Dim moduleName As String = thisProcess.MainModule.ModuleName
Dim processName As String = System.IO.Path.GetFileNameWithoutExtension(moduleName)
For Each p As Process In Process.GetProcessesByName(processName)
If p.Id <> thisProcess.Id AndAlso _
p.MainModule.FileName = thisProcess.MainModule.FileName Then
Return True
End If
Next p
End Function -- Mike

shaul_ahuva
03-28-2006, 07:17 PM
And another one, this time using a mutex.


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:

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

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum