Link to home
Start Free TrialLog in
Avatar of Erick37
Erick37Flag for United States of America

asked on

Multiple Instance Prevention?

In C, it's easy to prevent multiple instances of your application from running:
if (hPrevInstance) return FALSE;

Why is it so hard in VB?  Microsoft offers a 10 line solution, which I have read is unreliable:
Private Sub Form_Load()
  If App.PrevInstance Then
    SaveTitle$ = App.Title
    App.Title = "...duplicate instance"
    Form1.Caption = "...duplicate instance"
    AppActivate SaveTitle$
    SendKeys "% R", True
    End
  End If

So, here's my question:
What is wrong with using this bit of code, placed in a module, and setting the startup code as Main()?
Sub Main()
  If App.PrevInstance Then
     End
     Exit Sub
  Else
     Form1.Show
  End If
End Sub
Avatar of Anita030598
Anita030598

You can do it that way. You can even make it shorter this way

Sub Main()
 If Not App.PrevInstance Then
     Form1.Show
 End If
End Sub
 Anita, what Erick37 asked was not "the code worked or not"? There should something wrong with that code.

  The code is correct, when you trace the code in VB IDE, it won't work due to the program you trace is in VB process space. If you compile the code to exe file, then you would find it work.

  The other thing is, App.PrevInstance only work if the application is being invoked through Windows shell(eg. double click at the program in Windows Explorer). If you use CreateProcess to call the application in other program (one of the previous instance of the application already running), the code won't work. Use function shell or API ShellExecute to execute the application will still work for the code.

P.S. If my comment suit your question, please reject the answer and let me relock it. Thanks. :)
 
 
Avatar of Erick37

ASKER

Anita,
I know the code works, I have tried it.  My real question is it OK to terminate a second instance in this way?  **I want to be sure that no thunks of code from the second instance remain in memory after the End statement.**  If they do, then every time a second instance starts, program memory will be clogged with the dead code.
There has to be something too simple about my method (see question #2493) because I have read a method of terminating a second instance that requires over 100 lines of code and API calls.  What am I missing?
As far I know it is absolutely fine doing the way you are doing.
There will not be any memory clogging.
I didn't want to make it as an answer, but I guess I did huh?

Anyway, if you want to wait for others answers/comments you can reject this. But I am sure I have used the same way in many of my applications and did not have any problems.
Avatar of Erick37

ASKER

Anita:
Great, I love simplicity.  I will wait a bit for other comments on this subject before "grading" the answer.
Another point:
You proposed the following replacement code,
Sub Main()
       If Not App.PrevInstance Then
           Form1.Show
       End If
      End Sub

However, there is no End statement which removes the program and its objects from memory.  How can this work?
In your case End is not really needed. Because no objects or anything is loaded already.

Even otherwise, I would suggest not to use END anywhere. All the objects you create in your program should be removed from memory by setting it to Nothing. I know many people use End statement to do that, but it's not a good way to do that.

Anyway, I would say in this case you do not need END.
Your code works to prevent multiple instances, there's no problem with it, but it lacks the finesse of the original example which sets a focus on the previous instance, letting the user "fire up" the existing instance of the program.
Anita is correct.
Cymbolic is correct too.
Never use the End statement in your program, nor should you press the stop button in the design environment; both halt execution immediately without executing the Terminate events of any objects. It's always better to shut down your application by unloading all of the forms.
The 100 line version probably cycles through all of the loaded windows checking the title of each; this is necessary 1) in versions of VB that don't have the App object and 2) some rare cases when the program adapts itself based on what it is showing which causes the App object not to work (this must be done intentionally).
This isn't C; if you don't load anything, then when sub main ends then nothing is loaded or running so the program ends. I assume you are thinking of statements required in other languages to completely remove the app from memory; but, that code is built into your exe by VB automatically.

Avatar of Erick37

ASKER

Thanks to all who have helped me on this, now I understand.  My app runs in the system tray, so I don't need the finesse of activating it if someone tries to load another instance. I did use the code Anita suggested, and it works great (as long as it is the first bit of code to execute).  So if you would like the points, Anita, please post an answer to lock the question.

Thanks, Eric.
Avatar of Erick37

ASKER

P.S. Microsoft Support Online's example above uses the "End" statement. Hmmmm
End is OK in the Main(), as no form has been loaded yet.

Sub Main()
  If App.PrevInstance Then End  ' or MsgBox "Already running...: :  End
End Sub

Otherwise, never use the End statment.
End is OK in the Main(), as no form has been loaded yet.

Sub Main()
  If App.PrevInstance Then End  ' or MsgBox "Already running..." : End
End Sub

Otherwise, never use the End statment.
ASKER CERTIFIED SOLUTION
Avatar of Anita030598
Anita030598

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial