Page 1 of 1

Detect is program is already running

Posted: Fri Feb 08, 2008 8:23 pm
by Karbon
I *know* this has been discussed in here over the years but I sure can't seem to get the forum search to give me anything..

Pretty standard stuff, I want to be able to detect if an application I'm writing is already running. Too many people tend to start and re-start and re-re-start software - I want to be able to prompt them and ask them if they really want a new instance or if they want to activate one of the others.

Is there a way to do that reliably without using the window title of the application? I'd prefer to use the EXE's name if possible.. Is it also possible to bring the focus to the already running application's main window?

Thanks guys!

Posted: Fri Feb 08, 2008 8:31 pm
by Pupil

Posted: Fri Feb 08, 2008 8:35 pm
by Karbon
Duh, I should have searched for "single instance". I think that's the only phrase I didn't search for!

Thanks!!

Re: Detect is program is already running

Posted: Fri Feb 08, 2008 10:26 pm
by TerryHough
Karbon wrote:Is there a way to do that reliably without using the window title of the application? I'd prefer to use the EXE's name if possible.. Is it also possible to bring the focus to the already running application's main window?
Is there a real reason you don't want to use the window title? That has always worked perfectly for me.

What you want to do is about 7 lines of code if you can live with the window title.

Posted: Fri Feb 08, 2008 10:33 pm
by Karbon
Of course there is a real reason :-)

The window title changes to include information about what the user is doing (it shows the name of the company they're working in). Using part of the window title doesn't work very well either since the same word(s) could be in the title of web browsers visiting the product's site and such. I could come up with a unique string to stick in the title but that would look pretty goofy. It seems like using the process name is exponentially more reliable to me but it has always been on the bottom of my priority list until today..

Thanks!

Posted: Fri Feb 08, 2008 11:12 pm
by harff182
I found something in the German board: http://www.purebasic.fr/german/viewtopi ... 31&start=8

hth... scholly

Posted: Fri Feb 08, 2008 11:20 pm
by Rescator
Try the following:

Code: Select all

EnableExplicit

Define program_name$
program_name$="My Really Cool Program"
Enumeration #WM_USER+1
 #MYAPP_SHOW_MAINWINDOW ;A message we'll check for in our window callback
EndEnumeration



;This is the really cool code, put this near the start of your program.
Global msg_myapp.l
Define.l hmutex,result
msg_myapp=RegisterWindowMessage_(program_name$)
If msg_myapp=#False ;Error, may want to use GetLastError_() to check what.
 End
EndIf
SetLastError_(0)
hmutex=CreateMutex_(#Null,#True,@program_name$)
result=GetLastError_()
If (hmutex<>#False) And (result=#ERROR_ALREADY_EXISTS)
 PostMessage_(#HWND_BROADCAST,msg_myapp,#MYAPP_SHOW_MAINWINDOW,#True)
 CloseHandle_(hmutex)
 End
Else
 If result
  If hmutex : CloseHandle_(hmutex) :EndIf
  End
 EndIf
EndIf
And then:

Code: Select all

  ;use this code in the window callback.
  Case msg_myapp
   If wParam=#MYAPP_SHOW_MAINWINDOW And lParam=#True
    SetWindowState(#Window_Main,#PB_Window_Normal)
    SetForegroundWindow_(hwnd)
    SetActiveWindow(#Window_Main) ;not really needed unless you have multiple windows in the program I guess?
   EndIf
I'll leave the rest of the code to you :P
Obviously you can get more creative with the program "name", like company + app name or something. Heck you could probably use a GUID as well.

If you do not need to notify the other "you" to un-minimize/come forward or whatever, then just ditch the windows message stuff and keep just the mutex stuff.

This is one of the easier and better ways to handle single instance,
the windows message stuff allows a user to start the program again to get the current running one "forward".

Posted: Fri Feb 08, 2008 11:25 pm
by Karbon
Thanks for that!

Posted: Fri Feb 08, 2008 11:38 pm
by Rescator
Fixed the comment on the line: If msg_myapp=#False

PS! I use that code in several of my apps, works great :)

Posted: Sat Feb 09, 2008 2:00 am
by akj
This is the procedure I always use:

Code: Select all

#Program$ = "Name of my program"

Procedure AlreadyRunning() ; AKJ  30-Jan-07
; 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

; Main program
AlreadyRunning()
...
End