Start a program just one time

General FreeBASIC programming questions.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Start a program just one time

Post by deltarho[1859] »

jj2007 wrote:As UEZ noted, the MessageBox serves only to simulate the running program. When it finishes, the atom must be deleted.
I went to MSDN to read up on the Atom functions and I can now see what UEZ and jj2007 are saying.

So, with jj2007's original code the MessageBox is dual purpose: Firstly to tell us of a sucessful start; Secondly to simulate running code. However, the second purpose is not explained to us. When UEZ replaced the MessageBox with Sleep no explanation is given there either.

jj2007's original code with an explanation could be:

Code: Select all

#include "Windows.bi"
Dim ItsMe as string=Command(0)
If GlobalFindAtom(ItsMe) Then
  Messagebox Null, ItsMe+" is already running", "Sorry:", MB_IconWarning Or MB_Topmost
else
  Dim IsRunning as short=GlobalAddAtom(ItsMe)
  ' ##########
  '
  ' <-- Your application here
  '
  ' ##########
  GlobalDeleteAtom(IsRunning)
End If 

To test the method replace '<-- Your application here' with either a MessageBox or Sleep.

I take the view that is convoluted code.

With my method I simply add a simple construct to my application.

Code: Select all

If FirstInstanceOfProgram = 0 Then
  Messagebox Null, "<Whatever> is already running", "Title", MB_IconWarning Or MB_TaskModal Or MB_Topmost
  End
End If
If FirstInstanceOfProgram is in an inc file as a Private function then if the construct is not used FirstInstanceOfProgram will not get loaded.
UEZ
Posts: 988
Joined: May 05, 2017 19:59
Location: Germany

Re: Start a program just one time

Post by UEZ »

The disadvantage of jj2007's atom version is when you forget to use GlobalDeleteAtom(IsRunning) or the program crashes then the atom with Command(0) already exists.

How does the check will know if it was started the first time?
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Start a program just one time

Post by deltarho[1859] »

We can remove the convolution with the following but UEZ's last post still holds.

Code: Select all

'#Console On
#include "Windows.bi"
Dim Shared IsRunning as short
Dim ItsMe as string=Command(0)
If GlobalFindAtom(ItsMe) Then
  Messagebox Null, ItsMe+" is already running", "Sorry:", MB_IconWarning Or MB_Topmost
  End
Else
  IsRunning = GlobalAddAtom(ItsMe)
End If
 
' ##########
'
' <-- Your application here
'
' ##########
 
' To test
Print "Done"
Sleep
 
GlobalDeleteAtom(IsRunning)
SARG
Posts: 1766
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Start a program just one time

Post by SARG »

jj2007 wrote:@Sarg: without ReleaseSemaphore, you risk having a different functionality
Just curious what risk ?
Here the semaphore is no more than a flag (not a counter) and it's destroyed when exiting properly the program or if there is a crash.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Start a program just one time

Post by jj2007 »

SARG wrote:
jj2007 wrote:@Sarg: without ReleaseSemaphore, you risk having a different functionality
Just curious what risk ?
Here the semaphore is no more than a flag (not a counter) and it's destroyed when exiting properly the program or if there is a crash.
Can you post a complete example then?
UEZ
Posts: 988
Joined: May 05, 2017 19:59
Location: Germany

Re: Start a program just one time

Post by UEZ »

@SARG: I've tested your semaphore version and it works properly - simple and short.

According to MS: "Use the CloseHandle function to close the handle. The system closes the handle automatically when the process terminates. The semaphore object is destroyed when its last handle has been closed."

Code: Select all

'By SARG
#Include "windows.bi"

If CreateSemaphore(0, 0, 1,"&]8h/x87</htFV4-K*&.b.w~" ) <> 0 And GetLastError() = ERROR_ALREADY_EXISTS Then
   If MessageBox(0, "An other occurence is already running." + Chr(13) + "Continue ?", "Test", MB_YESNO Or MB_ICONQUESTION Or MB_SYSTEMMODAL Or MB_DEFBUTTON1) = IDNO Then End 1
   ? "Running another instance"
Else
	? "Running 1st instance"
End If
Sleep
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Start a program just one time

Post by deltarho[1859] »

Interestingly we can use a random string with the semaphore method as I do with the mutex method. The code is compact and there is no convolution - we can just drop the code into an application, and we don't have to remember to use GlobalDeleteAtom(IsRunning).

I also like SARG's YES/NO MessageBox, so we can allow another instance if wanted.

I believe we have a winner. Well done SARG and UEZ.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Start a program just one time

Post by jj2007 »

UEZ wrote:The system closes the handle automatically when the process terminates. The semaphore object is destroyed when its last handle has been closed.
Thanks, that makes the difference: atoms are one of the rare objects that don't get destroyed by ExitProcess. Well done, SARG!
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Start a program just one time

Post by deltarho[1859] »

@SARG

Would you have an objection to my publishing your solution on the PowerBASIC forums?
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Start a program just one time

Post by jj2007 »

deltarho[1859] wrote:Interestingly we can use a random string with the semaphore method
You can also safely use Str(GetTickCount())
SARG
Posts: 1766
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Start a program just one time

Post by SARG »

@deltarho
No problem. "Good" code should be shared. ;-)
Put the link and I'm going to read it.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Start a program just one time

Post by deltarho[1859] »

jj2007 wrote:You can also safely use Str(GetTickCount())
The random string needs to be designed once, used many times - GetTickCount is changing.
SARG wrote:Put the link and I'm going to read it.
If you agreed I intended doing that. Image
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Start a program just one time

Post by deltarho[1859] »

jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Start a program just one time

Post by jj2007 »

deltarho[1859] wrote:
jj2007 wrote:You can also safely use Str(GetTickCount())
The random string needs to be designed once, used many times - GetTickCount is changing.
Oops, you are right. So it might be handier to use the full path of the executable.
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Start a program just one time

Post by deltarho[1859] »

jj2007 wrote:So it might be handier to use the full path of the executable.
Nope. From MSDN,
"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 (\)."

Sorry. Image

Just type at random sufficiently long to have a decent entropy and make sure you use a different name with another application. I use KeePass for generating alpha-numeric random strings.
Post Reply