Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

Hello, here comes another question.

 

Isnt there any easy way to disable my application to start twice?

I cant accept that there are running two instances of my application at the same time..

 

I think there is a way withing VS.net where you can turn this off..

 

Any1 knows ?

 

Thx, Sandallic

Posted

I have this solution that works perfectly well for me...

Maybe Mutex is a better option but I leave you to choose...

 

Module Global
   Declare Function ShowWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal nCmdShow As Long) As Long

   Public Sub main()

       'Evaluate if this application is already running on this computer
       Const SW_MAXIMIZE = 3
       Const SW_SHOWMINIMIZED = 2
       Const SW_RESTORE = 9
       Const SHOWNORMAL = 1
       Const SW_SHOW = 5
       Dim processes() As Diagnostics.Process = Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)
       If processes.Length > 1 Then

           Dim mProcess As Diagnostics.Process
           For Each p As Diagnostics.Process In processes
               If mProcess Is Nothing Then
                   mProcess = p
               Else
                   If p.StartTime < mProcess.StartTime Then mProcess = p
               End If
           Next

           Dim hwnd As IntPtr = mProcess.MainWindowHandle

           Call ShowWindow(hwnd, SW_SHOWMINIMIZED)
           Call ShowWindow(hwnd, SHOWNORMAL)
           Call ShowWindow(hwnd, SW_SHOW)

           Exit Sub
       End If

       Application.EnableVisualStyles()
       Application.DoEvents()

       Application.Run(New StartForm)
   End Sub

End Module

 

This code not only block a second instance but also shows the application...

 

Alex :p

Software bugs are impossible to detect by anybody except the end user.
Posted

AlexCode, your code can be easily modified to use mutexes and show the previous instance. That way, there is no chance for your app to be shown twice, and you eliminate the need to loop through all the processes on the first run, which results in a (slightly?) quicker startup time:

Module Global
   Declare Function ShowWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal nCmdShow As Long) As Long
   Dim MyMutex As Threading.Mutex

   Public Sub main()
       'declare constants
       Const SW_MAXIMIZE = 3
       Const SW_SHOWMINIMIZED = 2
       Const SW_RESTORE = 9
       Const SHOWNORMAL = 1
       Const SW_SHOW = 5

       'Evaluate if this application is already running on this computer
       Dim NoPrevInstance As Boolean
       'I changed the string here to make it more obvious that it needs to be changed when this code is used:
       MyMutex = New Threading.Mutex(True, "Some String that's specific to your app", NoPrevInstance)
       If Not NoPrevInstance Then

           'if this application is already running, show it
           Dim processes() As Diagnostics.Process = Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)
           If processes.Length > 1 Then

               Dim mProcess As Diagnostics.Process
               For Each p As Diagnostics.Process In processes
                   If mProcess Is Nothing Then
                       mProcess = p
                   Else
                       If p.StartTime < mProcess.StartTime Then mProcess = p
                   End If
               Next

               Dim hwnd As IntPtr = mProcess.MainWindowHandle

               'Why did you have these two lines in here:
               'Call ShowWindow(hwnd, SW_SHOWMINIMIZED)
               'Call ShowWindow(hwnd, SHOWNORMAL)
               Call ShowWindow(hwnd, SW_SHOW)

               Exit Sub
           End If
       End If

       Application.EnableVisualStyles()
       Application.DoEvents()

       Application.Run(New StartForm)
   End Sub

End Module

 

By the way, why did you have those two extra ShowWindow lines?

Posted

Hi...

 

1st - When I did that code I din't knew about Mutex, and after knowing about it I didn't had much intetntion to modify it, since the performance increse shounldn't be "felt"... But shure it's more "clean" and "correct" code...

 

2nd - Those 2 extra line you queried about...

At least on my combuter (try it on yours to see if it's "universially" true), if the windows isn't minimized (if it's only behind others), the SHOW doesn't activate the window as expected, only shows it...

The correct behaviour only ocurres when the window is minimized... so, I minimize it (Call ShowWindow(hwnd, SW_SHOWMINIMIZED)), then I show the window with its last size and location (Call ShowWindow(hwnd, SHOWNORMAL)) and finally I call the show to make shure it gets active (Call ShowWindow(hwnd, SW_SHOW)).

 

Like I said, try it if the same behaviour error ocurres with you... if not, just use the last line...

 

By the way... thanks for the code "facelift"... :D

 

Alex :p

Software bugs are impossible to detect by anybody except the end user.
Posted

Hummmm great hint Plausy...

 

I didn't tested it in that environment... what hapens?

It gets confused with the instances or just doesn't work?

 

Alex :p

Software bugs are impossible to detect by anybody except the end user.
Posted

On my computer, the performance difference is noticable. Skipping the search through the processes seems to save at least a good couple seconds.

 

After working with the code a bit, I see what you mean about needing those three calls. However, I've always done it with SetForeGroundWindow, anyway. You do still need one call to ShowWindow in case it's minimized. Also, while adding the Declare for SetForegroundWindow, I noticed that ShowWindow had Long's instead of Int32's. Is there a reason why that even still worked? Whatever the case, I changed them to Int32's:

Module Global
   Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As IntPtr) As Int32
   Declare Function ShowWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal nCmdShow As Int32) As Int32
   Dim MyMutex As Threading.Mutex

   Public Sub main()
       'declare constants
       Const SW_MAXIMIZE = 3
       Const SW_SHOWMINIMIZED = 2
       Const SW_RESTORE = 9
       Const SHOWNORMAL = 1
       Const SW_SHOW = 5

       'Evaluate if this application is already running on this computer
       Dim NoPrevInstance As Boolean
       MyMutex = New Threading.Mutex(True, "Some String that's specific to your app", NoPrevInstance)
       If Not NoPrevInstance Then

           'if this application is already running, show it
           Dim processes() As Diagnostics.Process = Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)
           If processes.Length > 1 Then

               Dim mProcess As Diagnostics.Process
               For Each p As Diagnostics.Process In processes
                   If mProcess Is Nothing Then
                       mProcess = p
                   Else
                       If p.StartTime < mProcess.StartTime Then mProcess = p
                   End If
               Next

               Dim hwnd As IntPtr = mProcess.MainWindowHandle

               'The way I would do it:
               Call ShowWindow(hwnd, SW_RESTORE)
               SetForegroundWindow(hwnd)

               Exit Sub
           End If
       End If

       Application.EnableVisualStyles()
       Application.DoEvents()

       Application.Run(New StartForm)
   End Sub

End Module

Posted

I got this error :

 

Additional information:
It is invalid to start a second message loop on a single thread.
Use Application.RunDialog or Form.ShowDialog instead.

 

with a break on the line

 Application.Run(New frmMain)

Development & Research Department @ Elven Soft
Posted
When you look at all the codes out there for making your app only start up once, you might've noticed that they are all in Subs called Main. This is for a reason. You are supposed to put a Sub Main in a Module (alternatively, you can put a Shared Sub Main in a Class, but I prefer the module). Then go to Project -> Properties. In the window that comes up, change "Startup Object" from your form to the Sub Main that you put in.
Posted (edited)
Hey I was reading this post and I was wondering if yall could tell me how to do this in C# or if there was a tutorial I could look at. Edited by RampagePS
Posted
Hey I was reading this post and I was wondering if yall could tell me how to do this in C# or if there was a tutorial I could look at.

 

Translate it yourself... It's not that hard and sooner or later you'll have to learn a little vb.net... at least to understand the code examples aroud the web... :p

Software bugs are impossible to detect by anybody except the end user.
Posted

I think it would be something like this

 

[CS]

using System.Diagnostics;

using Microsoft.VisualBasic;

using System;

using System.Data;

using System.Drawing;

using System.Windows.Forms;

using System.Collections;

using System.Runtime.InteropServices;

 

namespace Only_One_Instance

{

sealed class Global

{

[DllImport("user32", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]

public static extern int SetForegroundWindow(IntPtr hwnd);

[DllImport("user32", ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]

public static extern int ShowWindow(IntPtr hWnd, int nCmdShow);

static System.Threading.Mutex MyMutex;

 

public static void main ()

{

//declare constants

const int SW_MAXIMIZE = 3;

const int SW_SHOWMINIMIZED = 2;

const int SW_RESTORE = 9;

const int SHOWNORMAL = 1;

const int SW_SHOW = 5;

 

//Evaluate if this application is already running on this computer

bool NoPrevInstance = false;

bool temp_bool = NoPrevInstance;

MyMutex = new System.Threading.Mutex(true, "Some String that's specific to your app", out temp_bool);

if (! NoPrevInstance)

{

 

//if this application is already running, show it

System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(System.Diagnostics.Process.GetCurrentProcess().ProcessName);

if (processes.Length > 1)

{

 

System.Diagnostics.Process mProcess = null;

foreach (System.Diagnostics.Process p in processes)

{

if (mProcess == null)

{

mProcess = p;

}

else

{

if (p.StartTime < mProcess.StartTime)

{

mProcess = p;

}

}

}

 

IntPtr hwnd = mProcess.MainWindowHandle;

 

//The way I would do it :

ShowWindow(hwnd, SW_RESTORE);

SetForegroundWindow(hwnd);

 

return;

}

}

 

Application.EnableVisualStyles();

Application.DoEvents();

 

Application.Run(new Form1());

}

 

}

}

[/CS]

Development & Research Department @ Elven Soft
Posted

You can try this (VB.Net) :

 

If (UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0) Then

MsgBox(" Application is already running in another window")

End

End If

Posted
You can try this (VB.Net) :

 

If (UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0) Then

MsgBox(" Application is already running in another window")

End

End If

 

Read the complete thread and THEN you'll figure out why that code shouln't be used...

 

Alex :p

Software bugs are impossible to detect by anybody except the end user.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...