Making it so only one instance of a program can be opened

Everything else that doesn't fall into one of the other PB categories.
Mortamer
User
User
Posts: 36
Joined: Mon Dec 29, 2003 5:07 pm

Making it so only one instance of a program can be opened

Post 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?
FloHimself
Enthusiast
Enthusiast
Posts: 229
Joined: Wed May 14, 2003 3:38 pm
Location: Lüneburg - Germany

Post by FloHimself »

There is a Userlib called 'AppRunning' on www.purearea.net or read here.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6172
Joined: Sat May 17, 2003 11:31 am
Contact:

Post 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
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB - upgrade incoming...)
( The path to enlightenment and the PureBasic Survival Guide right here... )
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Making it so only one instance of a program can be opene

Post 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
User avatar
NoahPhense
Addict
Addict
Posts: 1999
Joined: Thu Oct 16, 2003 8:30 pm
Location: North Florida

Re: Making it so only one instance of a program can be opene

Post 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
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Post 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)
....
....

Don't try - DO it !
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

The simplest solution is:

Code: Select all

hwnd=FindWindow_(0,title)
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!
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

@rescator: good thing about Zapman*'s code is that it doesnt need a 100% correct string @ window title.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post 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!
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post 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.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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
Last edited by netmaestro on Wed Feb 22, 2006 7:58 am, edited 1 time in total.
BERESHEIT
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Post by zapman* »

Beautiful !
Don't try - DO it !
clipper
User
User
Posts: 44
Joined: Fri Aug 29, 2003 7:47 am
Location: Germany

Post 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
User avatar
Shardik
Addict
Addict
Posts: 2068
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post 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
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post 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.
Anthony Jordan
Post Reply