Page 1 of 1

Single Instance Application

Posted: Thu Sep 29, 2011 2:52 pm
by Psych
Much discussion has been had as to what is the best, most efficient way to create a single instance application.
The most common solution being the creation of a 'named mutex', however this method doesn't provide any functionality to inform the original application that an instance was attempted.
This little procedure (windows only) not only tests if the same program in running, it will also post a message to that programs message queue informing the application that another instance was started.
Very useful for tray apps where the program will appear from the tray if the user double clicks the program icon on the desktop.

Code:

Code: Select all

Procedure CheckAndPost(uniquename$,wmessage=#WM_APP,autopost=1)
	Protected fn$="Global\"+uniquename$,tmp
	RtlAdjustPrivilege_(30,1,0,@tmp)
	Protected fm=CreateFileMapping_(#INVALID_HANDLE_VALUE,#Null,#PAGE_READWRITE|#SEC_COMMIT,0,4,@fn$)
	If fm
		tmp=GetLastError_()
		Protected *vm=MapViewOfFile_(fm,#FILE_MAP_ALL_ACCESS,0,0,4)
		If *vm
			If tmp=#ERROR_ALREADY_EXISTS
				tmp=PeekL(*vm)
				If autopost
					PostThreadMessage_(tmp,wmessage,-1,-1)
				EndIf
				ProcedureReturn tmp
			Else
				PokeL(*vm,GetCurrentThreadId_())
			EndIf
		EndIf
	EndIf
EndProcedure
Usage:

Code: Select all

If CheckAndPost("my app name")
	End
EndIf
Global WINSTYLE=#PB_Window_ScreenCentered|#PB_Window_SystemMenu
If Not OpenWindow(1,#PB_Ignore,#PB_Ignore,300,300,"Single Instance",WINSTYLE)
	End
EndIf
Repeat
	Select WaitWindowEvent(10)
		Case #PB_Event_CloseWindow
			Break
		Case #WM_APP
			If EventlParam()=-1 And EventwParam()=-1
				MessageRequester("Single Instance","running")
			EndIf
	EndSelect
ForEver
You must supply an unique name to the procedure, as it is used in the creation of the shared memory.
The wmessage parameter is the message that will be posted to the running application, it defaults to #WM_APP but I prefer to create my own unique message using RegisterWindowsMessage() with the same unique string I pass to this procedure plus "_running", this way I only need check for that in the message loop (lparam and wparam are not needed).
autopost is self explanatory, put a 0 here and the routine wont post the message to the application.
The function will return 0 (not running) or the threadID of the running program, handy if you want to post more messages, etc.
Hope you like.
PS. I didn't check the forums before posting this, so if I've duplicated an existing method, appologies.

Re: Single Instance Application

Posted: Fri Sep 30, 2011 12:48 am
by IdeasVacuum
....very practical solution, thanks for sharing Psych 8)

Re: Single Instance Application

Posted: Sat Oct 01, 2011 7:43 pm
by Kwai chang caine
Works fine
Thanks for sharing 8)

Re: Single Instance Application

Posted: Fri Mar 29, 2024 4:34 am
by jacdelad
I tried this code with 6.10, but it does...nothing. Does anyone know why? I'm not firm with filemappings.

Re: Single Instance Application

Posted: Fri Mar 29, 2024 4:57 am
by idle

Re: Single Instance Application

Posted: Fri Mar 29, 2024 5:40 am
by jacdelad
Ah thanks, unfortunately my shift is over now and I'm not allowed to work for four days. :cry:

Happy Easter everyone!

Re: Single Instance Application

Posted: Fri Mar 29, 2024 6:13 am
by Quin
I made a tiny module to do this that fully works for me on Windows 10 with PB 6.10 -> https://www.purebasic.fr/english/viewtopic.php?t=83926