Page 1 of 2
Making it so only one instance of a program can be opened
Posted: Sun Jun 13, 2004 4:59 pm
by Mortamer
Ok, I'd like to know how to make it so that only one instance of a program can be opened. The only problem is, their might be copies of the program in different paths, and I dont want them to be able to open either if one is currently running. Any ideas?
Posted: Sun Jun 13, 2004 5:36 pm
by FloHimself
There is a Userlib called '
AppRunning' on
www.purearea.net or read
here.
Posted: Wed Jun 16, 2004 7:13 am
by blueznl
another way is using a 'broadcast' message, doing a kind of ping pong action:
1. first instance starts, sends out a message 'i'm here'
2. no reply -> i'm the only one
3. second instance starts, sends out a message "i'm here'
4. first instance replies: 'no you're not'
5. second instance sees the message and knows it's time to quit
Re: Making it so only one instance of a program can be opene
Posted: Wed Jun 16, 2004 8:06 am
by PB
> I'd like to know how to make it so that only one instance of a program
> can be opened.
Read the FAQ:
viewtopic.php?t=4876
Re: Making it so only one instance of a program can be opene
Posted: Wed Jun 16, 2004 4:43 pm
by NoahPhense
Mortamer wrote:Ok, I'd like to know how to make it so that only one instance of a program can be opened. The only problem is, their might be copies of the program in different paths, and I dont want them to be able to open either if one is currently running. Any ideas?
Here's my mutex lib. It's finished, but I haven't released it yet. Going
to release it with a few other tools that I use often. All libs will have
linked help files.
Download Here:
Mutex_Lib
Just drop this in \\PureBasic\PureLibraries\UserLibraries\
How to use:
Code: Select all
; mutex example
OpenMutex("whatever")
MessageBox_(0,"Hello World!", "mutex example", 0)
CloseMutex()
End
- np
Posted: Wed Jun 22, 2005 10:52 pm
by zapman*
A shorter solution:
Code: Select all
#ProgName = "MyProgram"
;
Procedure IsLaunched (Name$)
Handle=0
Hwnd = FindWindow_( 0, 0 )
While Hwnd <> 0
Txt.s = Space(256)
GetWindowText_(Hwnd, Txt, 256)
Hwnd = GetWindow_(Hwnd, #GW_HWNDNEXT)
If Left(Txt,Len(nom$)) = Name$
Handle=Hwnd
Hwnd=0
EndIf
Wend
ProcedureReturn (Handle)
EndProcedure
;
If IsLaunched (#ProgName)
End
EndIf
OpenWindow(0,PosX,PosY,420,280,#PB_Window_ScreenCentered,#ProgName)
....
....
Posted: Thu Jun 23, 2005 7:13 pm
by Rescator
The simplest solution is:
If hwnd is 0 it wasn't found, if found it's the handle!
Windows only report the first window matching the name!
Then again, if two programs have the same name
there is no easy way to tell them apart, the code in the post above would have the same issue!
Posted: Fri Jun 24, 2005 12:28 am
by thefool
@rescator: good thing about Zapman*'s code is that it doesnt need a 100% correct string @ window title.
Posted: Sat Jun 25, 2005 12:45 am
by Rescator
That could cause issues you know!
And one should never use version numbers and so on in window titles!
A user could be running a old version for example!
My advice is to do something ala "Program Name (c) blablah"
or similar. chances of two programs with same title and copyright is extreemly slim!
Posted: Sat Jun 25, 2005 9:18 am
by thefool
yeh.. however in this case, the most safe thing is to use noah's lib as that will work even if the user changes the title.
Posted: Thu Jul 07, 2005 5:28 am
by netmaestro
Here is a little code snippet that works beautifully and is elegantly short. It works on the semaphore principle, where you attempt to create a semaphore when your program starts. If it exists, you end the program. The beauty of it is that the semaphore will be deleted automatically by Windows when the process that created it ends. Here is the one I use for my screensavers:
*a = CreateSemaphore_(null,0,1,"PreviewModeSemaphore")
If *a <> 0 And GetLastError_()= #ERROR_ALREADY_EXISTS
CloseHandle_(*a)
End
EndIf
Posted: Thu Jul 14, 2005 11:29 pm
by zapman*
Beautiful !
Posted: Tue Feb 13, 2007 9:40 am
by clipper
fixed Version of Zapmanns code
GetWindow_(Hwnd, #GW_HWNDNEXT)
must called after the if endif construct because
the hwnd from the next Window will returned by IsLaunched
Code: Select all
Procedure.l IsLaunched(Name$)
Hwnd = FindWindow_( 0, 0 )
While Hwnd <> 0
Txt.s = Space(256)
GetWindowText_(Hwnd, Txt, 256)
If Left(Txt,Len(Name$)) = Name$
ProcedureReturn Hwnd
EndIf
Hwnd = GetWindow_(Hwnd, #GW_HWNDNEXT)
Wend
ProcedureReturn #False
EndProcedure
Posted: Tue Feb 13, 2007 1:34 pm
by Shardik
@clipper:
You shouldn't use the FindWindow() approach because it is unreliable. Take a look into the following thread:
http://www.purebasic.fr/english/viewtopic.php?t=23351
And please read about the problems with FindWindow():
http://www.developerfusion.co.uk/show/1716/5
Posted: Tue Feb 13, 2007 7:09 pm
by akj
For a long time I have been using this procedure and am very happy with it:
Code: Select all
Procedure AlreadyRunning()
; Ensure the current program is not already running
; Terminate this process if it is
; Uses #Program$
Protected app, msg$
app=CreateSemaphore_(0,0,1,"AKJ "+#Program$)
If app<>0 And GetLastError_()=#ERROR_ALREADY_EXISTS
CloseHandle_(app) ; This line can be omitted
msg$="The "+#Program$+" program is already running."+#CRLF$+#CRLF$
msg$+"This process will terminate."
MessageRequester(#Program$+" Error", msg$, #MB_ICONERROR)
End
EndIf
EndProcedure
In my main code I set #Program$ to the name of my program before calling the Alreadyrunning() routine.
FYI the text "AKJ" (my initials) is included to reduce the probability that my semaphore name duplicates that of a semaphore already in use.