Check whether your application is running: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
No edit summary
(No difference)

Revision as of 13:12, 30 June 2010

Author: saabz_500 (talk, contrib)


There are many methods to detect whether your application is running or not.

It is much better to implement a method that involve some kind of cooperation from your application so that you are sure that you will detect your application specifically. However many of these methods also work without specific cooperation from the application.

Choose your method below, and place the adequate code inside your installer

Function .onInit
    ...
FunctionEnd

or your uninstaller:

Function un.onInit
    ...
FunctionEnd

using a DDE server

If the application implements a DDE server, your (un)installer can use the nsisDDE plug-in to contact the DDE server to query its state, bring the application to the foreground or ask the application to exit.

If your application is written in MFC, it is very easy to add a DDE server in it.. (use GuidGen tool to generate a unique service identifier specific to your application)

Many applications already implement such a DDE server (typically used by Explorer to open/print documents). You can search for "ddeexec" keys under HKEY_CLASSES_ROOT to find the name of applications' DDE server.

Examples:

nsisDDE::Execute "MyApp-{5A60A807-D40C-4554-935A-E570B818DF75}" "[Quit]"
Pop $0
IntCmp $0 0 notRunning
    Sleep 2000 ; give 2 seconds for the application to finish exiting
notRunning:
nsisDDE::Execute "MyApp-{5A60A807-D40C-4554-935A-E570B818DF75}" "[SetForeground]"
Pop $0
IntCmp $0 0 notRunning
    MessageBox MB_OK|MB_ICONEXCLAMATION "MyApp is running (foreground window). Please close it first" /SD IDOK
    Abort
notRunning:

using a Win32 Synchronization Object

Many applications typically create a named mutex to prevent multiple instance of the application. Your (un)installer could call the Win32 API "OpenMutex" to detect if this named mutex is active.

If you don't have access to the application source code, you can use tools like ProcessExplorer to find the synchronization objects owned by an application.

Example:

System::Call 'kernel32::OpenMutex(i 0x100000, b 0, t "MyAppMutex") i .R0'
IntCmp $R0 0 notRunning
    System::Call 'kernel32::CloseHandle(i $R0)'
    MessageBox MB_OK|MB_ICONEXCLAMATION "MyApp is running. Please close it first" /SD IDOK
    Abort
notRunning:

Advanced applications may use other Win32 named synchronization objects like an Event or Pipe to send a signal or a command to the application.

using the name of the process

You can detect if your application is running by using FindProcDLL plug-in to check if a process having the name of your application executable is running.

Make sure your application executable has an easily identifiable name, or you risk detecting another unrelated application having the same name as yours.

Example:

FindProcDLL::FindProc "MyApp.exe"
IntCmp $R0 1 0 notRunning
    MessageBox MB_OK|MB_ICONEXCLAMATION "MyApp is running. Please close it first" /SD IDOK
    Abort
notRunning:

using a window class

If your application creates a (main) window with a specific classname or title, you can use it to detect whether the application is running.

Unless you're sure of the application behaviour, be aware that many applications have dynamically generated window classname (different each time), and localized window title depending on the user language.

You can use Visual Studio tool Spy++ or freeware tool SysTree++ to find the window class of your application.

Examples:

FindWindow $0 "MyAppWindowClass"
StrCmp $0 0 notRunning
    MessageBox MB_OK|MB_ICONEXCLAMATION "MyApp is running. Please close it first" /SD IDOK
    Abort

or

FindWindow $0 "" "MyApp Window Title"
StrCmp $0 0 notRunning
    MessageBox MB_OK|MB_ICONEXCLAMATION "MyApp is running. Please close it first" /SD IDOK
    Abort

using a registry entry

Your application could, for example, write 1 on startup in a registry entry, and write 0 when the application is closed. You can then test this registry in your (un)installer.

However this solution is not clean because the registry would not be reset to 0 if your application crashes or is forcibly killed.

Example:

ReadRegDWORD $R0 HKLM "SOFTWARE\MyCompany\MyApp" "IsRunning"
IntCmp $R0 0 notRunning
    MessageBox MB_OK|MB_ICONEXCLAMATION "MyApp is running. Please close it first" /SD IDOK
    Abort
notRunning: