Conditional check if program is running

Just starting out? Need help? Post your questions and find answers here.
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Conditional check if program is running

Post by doctorized »

I make an app that reads and writes data to a db. I want to be able to have only one instance of my app running from the current directory.
At program startup, I want to check for other instances. If instance found from the current directory, exit. If instance found from another directory, continue. I found some codes here in this forum but I am having hard tome to make it work as I want to.
The code is:

Code: Select all

Global ProductID$ = GetCurrentDirectory() + "MyApp"
Global Mutex = CreateMutex_(0,1,@ProductID$)

If Mutex = 0 Or GetLastError_() = 183;ERROR_ALREADY_EXISTS
	MessageRequester("","Program already running!",#MB_ICONERROR)
Else
	MessageRequester("","No other instances.",#MB_ICONINFORMATION)
EndIf
Using GetCurrentDirectory() brings GetLastError_() with 183. Without it, it runs finding instances from other directories. Any ideas?
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Re: Conditional check if program is running

Post by Jeromyal »

Code: Select all

UseMD5Fingerprint()

ProcedureDLL.l Instance_Mutex(Lock.s)
  Protected *Mutex
  *Mutex = CreateMutex_(#Null, 1, Lock)
  If *Mutex <> 0 And GetLastError_() = #ERROR_ALREADY_EXISTS
    CloseHandle_(*Mutex)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

If Instance_Mutex(FileFingerprint(ProgramFilename(), #PB_Cipher_MD5)) 
  End 0
EndIf
You can place what ever you want in the procedure call instead of the md5 checksum I used. such as...

Code: Select all

if Instance_Mutex(ProgramFilename())
so that should do exactly what you desire.
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: Conditional check if program is running

Post by BarryG »

Don't use GetCurrentDirectory() as part of the mutex name, because that directory can be changed at runtime. Just use a unique static name that doesn't depend on runtime data. Even Jeromyal's version can fail if an older build of the exe is run at the same time as a newer, because the MD5 checksums of both exes won't match; thus allowing two instances to be run.
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Re: Conditional check if program is running

Post by Jeromyal »

BarryG wrote: Wed May 04, 2022 1:22 am Don't use GetCurrentDirectory() as part of the mutex name, because that directory can be changed at runtime. Just use a unique static name that doesn't depend on runtime data. Even Jeromyal's version can fail if an older build of the exe is run at the same time as a newer, because the MD5 checksums of both exes won't match; thus allowing two instances to be run.
Valid points BarryG.
But what I understand from his post, He just does not want the current running application to be able to run from the same location as multiple instances yet be able to launch another instance as long as it is executed from a different directory. Perhaps my suggestion is unwise? I can not think of another way other than passing the applications path as the mutex string to do what he describes.
I am defiantly someone who is apt to do very unconventional things because frankly I am just an unprofessional hobbyist hack.
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: Conditional check if program is running

Post by BarryG »

You're right about the external vs same directory launch - I overlooked that, sorry. Your way would fine in that case.
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Conditional check if program is running

Post by Keya »

as pointed out, don't use GetCurrentDirectory() as it can change. This returns the base directory of your process file location:

Code: Select all

AppDir$ = GetPathPart(ProgramFilename())
Debug AppDir$
AZJIO
Addict
Addict
Posts: 2187
Joined: Sun May 14, 2017 1:48 am

Re: Conditional check if program is running

Post by AZJIO »

I can't find a link to the original (netmaestro).

Code: Select all

Define *a = CreateSemaphore_(#Null, 0, 1, ProgramFilename())
If *a And GetLastError_() = #ERROR_ALREADY_EXISTS
	CloseHandle_(*a)
; 	MessageRequester("","The program is already running")
	End
EndIf
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: Conditional check if program is running

Post by BarryG »

Jeromyal wrote: Wed May 04, 2022 5:44 amHe just does not want the current running application to be able to run from the same location
I just remembered that the user could copy and rename the copy in the same directory, so the MD5 hashes won't match and multiple instances can therefore be run from the same location.
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Re: Conditional check if program is running

Post by Jeromyal »

BarryG wrote: Wed May 04, 2022 8:31 am
Jeromyal wrote: Wed May 04, 2022 5:44 amHe just does not want the current running application to be able to run from the same location
I just remembered that the user could copy and rename the copy in the same directory, so the MD5 hashes won't match and multiple instances can therefore be run from the same location.
Yeah that defiantly could cause trouble. Perhaps he should also test for a change in the name for safety?

Code: Select all

If GetFilePart(ProgramFilename()) <> "MyApp.exe"
  ; I don't know who I am anymore.
  End
EndIf
The MD5 does raise too many problems than it solves. I realized that with my own program I made and switched to a static string instead for my own latest build. Thanks to you bringing it to my attention BerryG
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Conditional check if program is running

Post by doctorized »

BarryG is right. I did not think of previous versions. I will try to help you guys by saying that what I really want is having only one app using the db. Why should a user run and use twice an app? I do not know. I want to avoid running multiple versions and instances of my app using the same db. That's why I talked about different folder in my initial post.
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Conditional check if program is running

Post by freak »

Your original code did not work because a backslash is not allowed in the mutex name:
The name can have a "Global" or "Local" prefix to explicitly create the object in the global or session namespace. The remainder of the name can contain any character except the backslash character (\).
See https://docs.microsoft.com/en-us/window ... eatemutexa

The code by Jeromyal avoids that by using the fingerprint of the path instead. Any other method to replace the backslash would probably work as well.
quidquid Latine dictum sit altum videtur
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: Conditional check if program is running

Post by BarryG »

doctorized wrote: Wed May 04, 2022 7:07 pmWhy should a user run and use twice an app?
Depends what it does. Think of an image viewer, or word processor, or web browser, or even PureBasic. They all need to be run more than once.
AZJIO
Addict
Addict
Posts: 2187
Joined: Sun May 14, 2017 1:48 am

Re: Conditional check if program is running

Post by AZJIO »

freak wrote: Wed May 04, 2022 9:46 pmbackslash is not allowed

Code: Select all

Define *a = CreateSemaphore_(#Null, 0, 1, ReplaceString(ProgramFilename(), "\", ":"))
If *a And GetLastError_() = #ERROR_ALREADY_EXISTS
	CloseHandle_(*a)
	MessageRequester("","The program is already running")
	End
EndIf

If OpenWindow(0, 0, 0, 220, 100, "One copy...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Conditional check if program is running

Post by doctorized »

AZJIO's code with GetCurrentDirectory() instead of ProgramFilename() solves my problem. I cannot use ProgramFilename() as every executable has the version number in its name, at least till now. Thank you very much for your time and answers!
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: Conditional check if program is running

Post by Marc56us »

doctorized wrote: Fri May 06, 2022 4:01 pm AZJIO's code with GetCurrentDirectory() instead of ProgramFilename() solves my problem. I cannot use ProgramFilename() as every executable has the version number in its name, at least till now. Thank you very much for your time and answers!
Numbered programs often start with the same prefix, so only one line is needed

Code: Select all

If GetFilePart( Left( ProgramFilename( ) ), 5) <> "MyApp"
Post Reply