[Solved] CreateMutex allowing multiple instances

Windows specific forum
BarryG
Addict
Addict
Posts: 4318
Joined: Thu Apr 18, 2019 8:17 am

[Solved] CreateMutex allowing multiple instances

Post by BarryG »

I've got this code near the start of my source:

Code: Select all

Global appmutex=CreateMutex_(0,1,"My_App_Unique_ID")
MessageRequester("RunOnce","Mutex: "+Str(appmutex))
But when I compile it to an exe and run several instances of it, the "appmutex" variable is always non-zero, meaning the mutex was successfully created for each instance (see screenshot).

However, it's not supposed to, and it should return 0 in the MessageRequester() when a match for the mutex name is already found. Same if I use a semaphore.

This used to work before to prevent multiple instances of my app (only run once), but not anymore. Using Windows 10 Pro, with both 32-bit and 64-bit of PureBasic 5.71. Any ideas?
Last edited by BarryG on Mon Nov 11, 2019 12:42 pm, edited 1 time in total.
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: CreateMutex allowing multiple instances

Post by Marc56us »

Forgot to test the return error?
GetLastError_()=#ERROR_ALREADY_EXISTS

Code: Select all

; Determine if only one instance is running
; https://rosettacode.org/wiki/Determine_if_only_one_instance_is_running#PureBasic
;
#MyApp="MyLittleApp"
Mutex=CreateMutex_(0,1,#MyApp)
If GetLastError_()=#ERROR_ALREADY_EXISTS
  MessageRequester(#MyApp,"One instance is already started.")
  End
EndIf
 
; Main code executes here
 
ReleaseMutex_(Mutex)
End
Source: https://rosettacode.org/wiki/Determine_ ... #PureBasic
Windows 10 x64 family: OK
(Not tested elsewhere) :wink:
BarryG
Addict
Addict
Posts: 4318
Joined: Thu Apr 18, 2019 8:17 am

Re: CreateMutex allowing multiple instances

Post by BarryG »

Solved. It was nothing to do with GetLastError_(), which yes, I was also checking but didn't show in my example. Here's how it was solved: my app, when detecting the existing mutex, was sending a #HWND_BROADCAST message to the first instance. However, since it was being done with SendMessage_(), the second instance wasn't returning to quit itself with "End". I simply changed SendMessage_() to PostMessage_() and it now works again.
User avatar
Michael Vogel
Addict
Addict
Posts: 2847
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: [Solved] CreateMutex allowing multiple instances

Post by Michael Vogel »

I'm using a code similar to Marc's example for many times but now I'd like to add a simple restart function to the program which could be useful in certain situation (e.g. DPI settings change)...

Without a delay the mutex seems to be still present, a fixed delay would work but is not elegante.

So I thought doing a loop trying to create a mutex until it works or timeout is reached. But I am wrong, the last error stays frozen - so what is wrong here?

Code: Select all

Procedure Main();										Needs to be compiled to MyApp.exe
	
	Protected s.s
	n=Bool(ProgramParameter(0)=".")*16;					Waits up to 1.5 seconds to see if no mutex is present...
	
	If n
		;Delay(1000);									/// would work then
	EndIf

	Repeat
		mutti=CreateMutex_(0,0,@"MyApp")
		m=Bool(GetLastError_()=#ERROR_ALREADY_EXISTS)
		s+Str(mutti)+": "+Str(m)+#CR$
		If m
			ReleaseMutex_(mutti)
			CloseHandle(mutti)
			Debug GetLastError_()
			n-1
			Delay(100)
			Debug Str(n)+", "+Str(mutti)
		EndIf
	Until m=0 Or n<0

	MessageRequester(Str(m)+", "+Str(n),s)

	If m
		ReleaseMutex_(mutti)

	Else
		OpenWindow(0,20,20,200,200,"")
		ButtonGadget(1,20,20,160,40,"Restart")
		ButtonGadget(2,20,120,160,40,"Quit")

		Repeat
			Select WaitWindowEvent()
			Case #PB_Event_Menu,#PB_Event_Gadget
				quit=EventMenu()
			EndSelect
		Until quit
	
		If quit=1
			RunProgram("MyApp.exe",".",".")
		EndIf
	EndIf

EndProcedure

Main()
Post Reply