tags:

views:

292

answers:

4

Hello.

I'm working on an NSIS installer, and trying to check if a certain application is running before uninstalling. So, I use kernel32::CreateMutexA call. Here is the chunk:

System::Call 'kernel32::CreateMutexA(i 0, i 0, t "cmd.exe") i .r1 ?e'
Pop $R0
StrCmp $R0 0 +3
    MessageBox MB_USERICON "The application is already running."
Abort

I put it into un.onInit. Trouble is, the process (cmd.exe here) is never detected.

Did I miss something?

Tx.

+1  A: 

All you are doing is creating a mutex with the global name "cmd.exe". From the MSDN article for CreateMutex:

If lpName matches the name of an existing event, semaphore, waitable timer, job, or file-mapping object, the function fails and the GetLastError function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same name space.

So unless cmd.exe creates a handle to one of those types of objects with the name "cmd.exe", this call will simply create a new mutex with that name and return you the (non-erronous) handle.

jdmichal
+1  A: 

You're probably using the wrong Win32 API function. Your CreateMutex tries to create a named mutex "something.exe". If there isn't one with that name it will succeed, so unless the process you're trying to check is creating a mutex with that name, you won't get the result you're after.

What you want is probably to enumerate all running processes and see if the one you're after is there. You can do this with ToolHelp32 from Win32 API - see sample here. I don't know how easy it will be to convert it to 'pure' NSIS so you might want to write a DLL plugin, or check if there's an existing solution floating around the NSIS community.

Idan K
Tx Idan.It's strange. When I try with the installer itself (e.g. `my_setup.exe`), it works! But not with another process.
Anonymous
what works? from your code example the messagebox will appear if CreateMutexA has succeeded - that is, there isn't a named mutex with the name you provided. regardless of the behavior you're getting, it's the wrong solution to the problem you're trying to solve.
Idan K
`CreateMutexA()` succeeds with the installer itself. So, it's actually the right solution to detect if there is a running instance of the installer. But as you said, not the good one for any other process.
Anonymous
Yes, using a named mutex to allow a single instance of the installer is the right solution. It just wasn't clear that this was your intention in the first place.
Idan K
A: 

For this kind of thing, I've used either the KillProcess or Find-Close-Terminate plugins for NSIS - see here

Documentation is pretty straightforward, hopefully this does what you need - with a fairly minimal overhead.

James Turner
+1  A: 

I found a simple solution; using FindProcDLL plugin.

So:

FindProcDLL::FindProc "cmd.exe"
Pop $R0
StrCmp $R0 0 +3
 MessageBox MB_USERICON "The application is already running." IDOK
Abort

P.S. FindProcDLL.dll must be copied into /Plugins.

Anonymous