|
-
Sep 19th, 2002, 01:53 PM
#1
Thread Starter
Hyperactive Member
Find previous instance (not App.PrevInstance)
How can my application know if there are any previous instances of this application running, and know when they have terminated.
I want my program to be able to sit and wait until any previous instance of itself has terminated, before displaying a form. So App.PrevInstance is no good because it does not refresh.
The title of the windows in this application will not be constant, the only thing I will know for sure is the path to, and name of the .exe file.
So basically;
Are there some API's I can use to determine if windows is running any instances of an executable, that's not the current instance..
Thanks
Last edited by brenaaro; Sep 19th, 2002 at 02:01 PM.
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
-
Sep 19th, 2002, 03:06 PM
#2
Hyperactive Member
App.PrevInstance doesn't work even if it's in a loop?
[vbcode]
' comment
Rem remark
[/vbcode]
-
Sep 19th, 2002, 03:08 PM
#3
Thread Starter
Hyperactive Member
No, it won't tell you if the previous instance has been closed after the initial check.
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
-
Sep 19th, 2002, 03:39 PM
#4
Software Eng.
You could probably get by with FindWindow.
-
Sep 19th, 2002, 03:45 PM
#5
Thread Starter
Hyperactive Member
If it ends up that the form caption will always be the same then I will use that. It looks like the caption may be a variable though, depending on an argument passed to the executable.
I'll probably end up keeping a running tally of process IDs in a file and cycle through them, checking which ones are open and such. Each instance would add/remove it's own process ID as it opens/closes
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
-
Sep 19th, 2002, 03:59 PM
#6
Frenzied Member
Use your own Mutex (App.PrevInstance is a mutex) - a mutual exclusion semaphore - maintained in kernel.
Name them like myapp1, myapp2... myappn.
Maintain them and check them, this limits your app to 10 instances.
Code:
Private Const ERROR_ALREADY_EXISTS = 183&
Private Const LIMIT = 10 ' we want no more than 10 instances of myapp
Dim myMutex as long
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Sub NewApp() as long ' run me when starting
Dim tmp as string, working as String
Dim x
tmp= App.Title
x=1
myMutex=0
Do while myMutex = 0
myMutex = TryMutex(tmp & x)
x = x + 1
if x > LIMIT then
msgBox "Too many instances of this app. Cannot Continue",vbOkOnly
end
end if
Loop
End Sub
Function CanIShowForm() as Boolean
dim instances as long
dim tmp,x
instances = 0
tmp=App.Title
for x=1 to LIMIT
instances = instacnes + TryMutex(tmp & x)
next
if instances = 1 then ' this is the only one out there
CanIShowForms = True
else
CanIShowForms = False
End if
End Function
Function TryMutex(name as String) as long
Dim hMutex as long
hMutex = CreateMutex(ByVal 0&, 1, name)
If (Err.LastDllError = ERROR_ALREADY_EXISTS) Then
ReleaseMutex hMutex
CloseHandle hMutex
TryMutex = 0
Else
TryMutex=hMutex
End If
End Function
Sub CLoseApp()
CloseHandle myMutex
Set Form1=Nothing
End
End Sub
-
Sep 19th, 2002, 04:01 PM
#7
Frenzied Member
Friendly warning
BE SURE! you close the mutex when you exit, even if it's an error.
If you are in development be sure you let the ide execute the CloseApp sub.
If you don't you cannot clear mutexes - they will build up and you will have to reboot.
-
Sep 19th, 2002, 06:13 PM
#8
Thread Starter
Hyperactive Member
Wow, thanks Jim! This is all new stuff to me.
I'll give it a try at work tomorow.
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
-
Sep 20th, 2002, 07:28 AM
#9
Thread Starter
Hyperactive Member
question
Just a quick question, what is CanIShowForm() supposed to do? When I ran through it, it created all remaining Mutex's (up to LIMIT).
Granted I could close them all by running through it again, but I was just curious. It looks like it's supposed to return a count of open Mutexes, but it just adds up the handles to those Mutes that it opens.
If I wanted to count the instances of Mutes, would I do something like this?
VB Code:
Function CanIShowForm() as Boolean
Dim instances as long
Dim tmp,x
instances = 0
tmp=App.Title
For x=1 to LIMIT
instances = instances + CountMutex(tmp & x)
Next
' = 0 instead of = 1?
If instances = 0 Then ' this is the only one out there
CanIShowForms = True
Else
CanIShowForms = False
End if
End Function
Function CountMutex(name as String) as long
Dim hMutex as long
hMutex = CreateMutex(ByVal 0&, 1, name)
'Don't want to close my own Mutex, correct?
If (Err.LastDllError = ERROR_ALREADY_EXISTS) And hMutex <> myMutex Then
ReleaseMutex hMutex
CloseHandle hMutex
CountMutex = 1
Else
'Also dont want to open any new ones?
ReleaseMutex hMutex
CloseHandle hMutex
End If
End Function
One more thing, the LIMIT of 10, was that an arbitrary number or is does it have significance? Thanks
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
-
Sep 20th, 2002, 08:53 AM
#10
I think a better solution would be to create a semaphore, with an initial count of 1, and a maximumcount of 1.
Call CreateSemaphore when your app starts, followed by a WaitForSingleObject. If your instance is the first, it will return immediately, otherwise it will wait untill the previous instance called ReleaseSemaphore.
When your app gets closed, call ReleaseSemaphore, followed by a CloseHandle.
This way, you don't have to poll untill you can show your form, the WaitForSingleObject simply returns as soon as it is your turn. Another advantage is that the instances will be running when it is their turn. The second instance will display the form, as soon as the first instance is ready, and the third instance as soon as the second instance is ready. semaphores automatically use the FIFO principle (First In First Out)
I will see if I can write a sample when I get home. I can't spent too much time right now, because i am at work.
-
Sep 20th, 2002, 09:07 AM
#11
Thread Starter
Hyperactive Member
Mutex, Semphores and more! Oh my!
Mutex, Semaphore..all one big heap of mumbo-jumbo to me at this point in time ;-)
I'll try seeing what MSDN has to say about Semaphores but if you can come up with an example that would be great.
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
-
Sep 20th, 2002, 09:07 AM
#12
Frenzied Member
Frans C suggestion is better in this case. I just went the way
App.Previnstance goes.
Sempahores work the same way mutexes do - you call create, get the handle, increment or decrement, then closehandle - but they are a flag that gets set. Think of them as an event flag.
-
Sep 20th, 2002, 10:00 AM
#13
OK, here it is.
Add a standard module to a project, and add this code.
Set your startup to Sub main.
VB Code:
Option Explicit
Private Declare Function CreateSemaphore Lib "kernel32" Alias "CreateSemaphoreA" (ByVal lpSemaphoreAttributes As Long, ByVal lInitialCount As Long, ByVal lMaximumCount As Long, ByVal lpName As String) As Long
Private Declare Function ReleaseSemaphore Lib "kernel32" (ByVal hSemaphore As Long, ByVal lReleaseCount As Long, lpPreviousCount As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const INFINITE = &HFFFF
Private lngSemaphore As Long
Private Const MaxInst As Long = 1 ' change this to 2, if you want a maximum of 2 instances to display the form at the same time
Sub Main()
Dim lngRet As Long
'A semaphore counts down to 0, because we start at 1 only one instance will show the form at the same time
' create the semaphore. If a previous instance exists, this function returns a handle to the existing one.
lngSemaphore = CreateSemaphore(0&, MaxInst, MaxInst, "MyCoolProgram")
' We wait untill we can start our form. If this is the first instance, we don't wait long.
' this call will decrease the counter. If the counter is at 0, it waits until another instance increases it
lngRet = WaitForSingleObject(lngSemaphore, INFINITE)
' Ok, now show the form
Form1.Show
End Sub
Public Sub Cleanup()
Dim lngRet As Long
' we increase the counter with 1, if other instances are waiting, the first one can stop waiting
lngRet = ReleaseSemaphore(lngSemaphore, 1&, 0&)
' close the handle
lngRet = CloseHandle(lngSemaphore)
End Sub
Add this code to form1
VB Code:
Private Sub Form_Unload(Cancel As Integer)
Call Cleanup
End Sub
-
Sep 20th, 2002, 11:10 AM
#14
Thread Starter
Hyperactive Member
Ok, looks simple enough.
Just a quick question about WaitForSingleObject.
Say I wanted the current instance to only wait 5 seconds for it's turn before giving up and closing.
I would pass 5000& to dwMilliseconds but does that mean that if it does not get it's turn after 5 seconds, it returns a timeout value (and what is the value for WAIT_TIMEOUT btw..)?
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
-
Sep 20th, 2002, 01:30 PM
#15
Ok, to wait only 5 seconds, pass 5000& as dwmilliseconds, like you already mentioned. If it times out, the retgurn value (lngRet )will be equal to WAIT_TIMEOUT (&H102).
If you want to exit after the timeout, you should not call ReleaseSemaphore (this would increase the counter, while you didn't decrease it), but you should close the handle.
So here is the modified code:
In a module:
VB Code:
Option Explicit
Private Declare Function CreateSemaphore Lib "kernel32" Alias "CreateSemaphoreA" (ByVal lpSemaphoreAttributes As Long, ByVal lInitialCount As Long, ByVal lMaximumCount As Long, ByVal lpName As String) As Long
Private Declare Function ReleaseSemaphore Lib "kernel32" (ByVal hSemaphore As Long, ByVal lReleaseCount As Long, lpPreviousCount As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const INFINITE = &HFFFF
Private Const WAIT_TIMEOUT = &H102
Private lngSemaphore As Long
Private Const MaxInst As Long = 1 ' change this to 2, if you want a maximum of 2 instances to display the form at the same time
Sub Main()
Dim lngRet As Long
'A semaphore counts down to 0, because we start at 1 only one instance will show the form at the same time
' create the semaphore. If a previous instance exists, this function returns a handle to the existing one.
lngSemaphore = CreateSemaphore(0&, MaxInst, MaxInst, "MyCoolProgram")
' We wait untill we can start our form. If this is the first instance, we don't wait long.
' this call will decrease the counter. If the counter is at 0, it waits until another instance increases it
lngRet = WaitForSingleObject(lngSemaphore, 5000&)
If lngRet <> WAIT_TIMEOUT Then
' Ok, now show the form
Form1.Show
Else
' close the handle
lngRet = CloseHandle(lngSemaphore)
End If
End Sub
Public Sub Cleanup()
Dim lngRet As Long
' we increase the counter with 1, if other instances are waiting, the first one can stop waiting
lngRet = ReleaseSemaphore(lngSemaphore, 1&, 0&)
' close the handle
lngRet = CloseHandle(lngSemaphore)
End Sub
The form code stays the same.
-
Sep 20th, 2002, 03:03 PM
#16
Thread Starter
Hyperactive Member
Perfect
Absolutely perfect.
I tried it all out and it works like a charm!
Thanks a bunch folks!
And I, for one, welcome our new insect overlords. I'd like to remind them as a trusted TV personality, I can be helpful in rounding up others to toil in their underground sugar caves.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|