Erick37
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
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
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. :)
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. :)
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?
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.
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.
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.
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?
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.
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.
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.
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.
Thanks, Eric.
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.
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.
Sub Main()
If App.PrevInstance Then End ' or MsgBox "Already running..." : End
End Sub
Otherwise, never use the End statment.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Sub Main()
If Not App.PrevInstance Then
Form1.Show
End If
End Sub