Single Instance Application...


Author
Message
Ivan George Borges
Ivan George Borges
Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)
Group: StrataFrame MVPs
Posts: 1.9K, Visits: 21K
Yep, that is it.

I go a bit further on my applications since I have a Licensing control based on licenses per machine. So I create the Mutex under a Global state, this way I can count the number of instances running even on various Terminal Service sessions.
Rogerio Mauri
Rogerio Mauri
StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)
Group: StrataFrame Users
Posts: 205, Visits: 629
Hi Ivan...

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            //-- Evita mais de uma instância
            bool ok;
            Mutex loMutex = new Mutex(true, Application.ProductName + Application.ProductVersion, out ok);
            if (!ok)
            {
                MessageBox.Show("Aplicativo já está em execução");
                Application.Exit();
                return;
            }

            //-- Enable visual styles on the application
            Application.EnableVisualStyles();


            ...

            //-- Run the application
            StrataFrameApplication.RunApplication();

            //-- Stop the session monitoring before the application exits to remove the low-level event handlers
            SessionLock.StopSessionMonitoring();


            GC.KeepAlive(loMutex);


        }




Rogério Mauri Smile



Ivan George Borges
Ivan George Borges
Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)
Group: StrataFrame MVPs
Posts: 1.9K, Visits: 21K
Hi Rogerio.

GetProcessByName is a lot simpler, but has some disavantages:
  • it will allow 2 instances to run if you change the .EXE name
  • if you have 2 separate applications with the same name, it won't allow them to run at the same time
  • Mutex can work with a Global escope, so it will make sure the application run only once in the entire system, even on Terminal Services
  • apparently, GetProcessByName may not access minimized windows properly

Rogerio Mauri
Rogerio Mauri
StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)StrataFrame User (303 reputation)
Group: StrataFrame Users
Posts: 205, Visits: 629
Code...

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            //-- Evita mais de uma instância
            if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
            {
                MessageBox.Show("Aplicativo já está em execução");
                Application.Exit();
                return;
            }

            //-- Enable visual styles on the application
            Application.EnableVisualStyles();

            //-- Add event handlers for the application events
            StrataFrameApplication.ShowGateway +=
                new StrataFrameApplication.ShowGatewayEventHandler(
                ShowGateway);

            ...

        }

 

Rogério Mauri Smile



Edhy Rijo
E
StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Larry,



Thanks for the information. I google this issue and found some different approaches, I combined two of them and was able to put together a solution that will will do just what is expected from the user: if the application is minimized, it will just bring it to the from.



Of course this solution is not as simple as using the Mutex and may have other issues since it uses the System.Diagnostics.Process to get to the application.



Ok here is the code.. Copy these 2 classes to a new class file in the main project I called mine "SingleInstance.vb" or if you have a based class in the main .exe project you could use that as well.



#Region " Code to handle a single instance of the application "



'Windows API

Declare Function OpenIcon Lib "user32" (ByVal hwnd As Long) As Long

Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long



'''

''' Function to check and see if an instance of the application is already open

'''


''' Name of the application

''' True/False

'''

Public Shared Function IsAlreadyOpen(ByVal sApp As String) As Boolean

'Check running processes to see if application is already running

Dim pProcess As Process() = System.Diagnostics.Process.GetProcessesByName(sApp)

If pProcess.Length > 1 Then 'If > 1 then its already running

Return True

Else 'Not running

Return False

End If

End Function



Public Shared Sub ActivatePrevInstance(ByVal argStrAppToFind As String)

Dim PrevHndl As Long

Dim result As Long



Dim objProcess As New Process 'Variable to hold individual Process

Dim objProcesses() As Process 'Collection of all the Processes running on local machine

objProcesses = Process.GetProcesses() ''Get all processes into the collection



For Each objProcess In objProcesses



If UCase(objProcess.ProcessName) = UCase(argStrAppToFind) Then

If Not String.IsNullOrEmpty(objProcess.MainWindowTitle) Then

'MessageBox.Show(objProcess.MainWindowTitle)

PrevHndl = objProcess.MainWindowHandle.ToInt32()

Exit For

End If

End If

Next

If PrevHndl = 0 Then Exit Sub 'if No previous instance found exit the application.

''If found

result = OpenIcon(PrevHndl) 'Restore the program.

result = SetForegroundWindow(PrevHndl) 'Activate the application.



End 'End the current instance of the application.

End Sub

#End Region





Now like in your case, to execute it in the AppMain.vb after the "Public Shared Sub Main()" add this code:



If SingleInstance.IsAlreadyOpen(My.Application.Info.ProductName) Then

SingleInstance.ActivatePrevInstance(My.Application.Info.ProductName)

Exit Sub

End If



Edhy Rijo

Larry Caylor
Larry Caylor
StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)
Group: Awaiting Activation
Posts: 592, Visits: 3.7K
What I actually ended up doing in my applications is to display a SF message telling the user that an instance was already running. I imagine there is probably some way to display the original instance but our users are fine with the message so that's where I left it.

-Larry

Edhy Rijo
E
StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Larry,



I also implemented your code and it does works well.



Instead of just exiting without letting the user know what may be happening, is there a way to simply show up the instance that is currently open?

Edhy Rijo

Ivan George Borges
Ivan George Borges
Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)Strategic Support Team Member (3.5K reputation)
Group: StrataFrame MVPs
Posts: 1.9K, Visits: 21K
Hi Larry.

Thanks for the code snippet. I was just trying to accomplish this, and it worked really fine.

Smooooth

StrataFrame Team
S
StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)
Group: StrataFrame Developers
Posts: 3K, Visits: 2.5K
Haha, yep, Larry, much simpler.  Good idea.
Larry Caylor
Larry Caylor
StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)
Group: Awaiting Activation
Posts: 592, Visits: 3.7K
Robin,

I've been using the mutex method for restricting an application to a single instance. It's easy to implement and so far it's worked well for me. By varying the safeName you should be able to over come the problem in Terminal Services.

 I include the following code at the top of Public Shared Sub Main in AppMain.

Dim firstInstance As Boolean = False
'-- Create a name based on the user application path.
Dim safeName As String = Application.UserAppDataPath.Replace("\", "_")
Dim myMutex As Mutex = New Mutex(True, safeName, firstInstance)
'-- Bail if not first instance.
If Not (firstInstance) Then Exit Sub
'-- Make sure the program holds the mutex as long as it is running.
GC.KeepAlive(myMutex)


See http://www.ai.uga.edu/mc/SingleInstance.html for more info.

-Larry


GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search