Can someone please assist with the proper way to call the createmutex API? What I am trying to do is to set a mutex flag while I am installing an update so that if my application is executed anytime during the update process, the application will not start until the mutex is released. An example would be great on how to do set the flag and remove it. Thanks
!define PATCHEXE "MutexTest.exe"
Name "Mutex Test"
OutFile "MutexTest.exe"
SilentInstall silent
Section "MainSection"
System::Call 'kernel32::CreateMutex( s, b, s) i(.r0, FALSE, "{E27D1C1E-B4D8-4439-83B4-0173E03C5D11}") .r3'
SectionEnd ; end the section
Need Help with Set and Release Mutex!
38 posts
1) You need to do is call this from .onInit so it will set the mutex when the installer starts and not when it starts installing.
2) You need to do is call CreateMutexA because there is no function called CreateMutex, only CreateMutexA for MBCS and CreateMutexW for Unicode.
3) You should specify t for strings and not s. Also, b is not a valid type, use i for int (same as BOOL).
4) lpMutexAttributes is a pointer and therefore should be defined as i and not s.
5) You need to call GetLastError after this call and compare it to ERROR_ALREADY_EXISTS (183) to know if the mutex already exists.
Your code should be (not tested, plesae test):
2) You need to do is call CreateMutexA because there is no function called CreateMutex, only CreateMutexA for MBCS and CreateMutexW for Unicode.
3) You should specify t for strings and not s. Also, b is not a valid type, use i for int (same as BOOL).
4) lpMutexAttributes is a pointer and therefore should be defined as i and not s.
5) You need to call GetLastError after this call and compare it to ERROR_ALREADY_EXISTS (183) to know if the mutex already exists.
Your code should be (not tested, plesae test):
Function .onInit
System::Call 'kernel32::CreateMutexA(i, i, s) i(0, 0, "myMutex")'
System::Call 'kernel32::GetLastError() i() .r0'
StrCmp $0 183 0 +3
MessageBox MB_OK "installer already running"
Abort
StrCmp $0 0 done
MessageBox MB_OK "error creating mutex, getlasterror didn't return success"
done:
FunctionEnd
This still is not working properly, this is what I tried, it provided me with no errors and allowed multiple instances.
!define PATCHEXE "MutexTest.exe"
Name "Mutex Test"
OutFile "MutexTest.exe"
SilentInstall silent
Function .onInit
System::Call 'kernel32::CreateMutexA(i, i, s) i(0, 0, "myMutex")'
System::Call 'kernel32::GetLastError() i() .r0'
StrCmp $0 183 0 +3
MessageBox MB_OK "installer already running"
Abort
StrCmp $0 0 done
MessageBox MB_OK "error creating mutex, getlasterror didn't return success"
done:
MessageBox MB_OK "mutex set"
FunctionEnd
Section Test
SectionEnd
!define PATCHEXE "MutexTest.exe"
Name "Mutex Test"
OutFile "MutexTest.exe"
SilentInstall silent
Function .onInit
System::Call 'kernel32::CreateMutexA(i, i, s) i(0, 0, "myMutex")'
System::Call 'kernel32::GetLastError() i() .r0'
StrCmp $0 183 0 +3
MessageBox MB_OK "installer already running"
Abort
StrCmp $0 0 done
MessageBox MB_OK "error creating mutex, getlasterror didn't return success"
done:
MessageBox MB_OK "mutex set"
FunctionEnd
Section Test
SectionEnd
The problem is between GetLastError and the actual function call there are some other functions called... I'll talk to the creator of the plug-in about finding a solution for this, but in the mean while you can use this little plug-in I have just created (attached). Here's an example:
Function .onInit
Mutex::Create "myMutex"
Pop $0
StrCmp $0 0 done
StrCmp $0 1 0 error
MessageBox MB_OK|MB_ICONSTOP "Installer already running..."
Abort
error:
MessageBox MB_OK|MB_ICONSTOP "Error creating mutex (probably bad mutex name)"
done:
FunctionEnd
Thanks alot, the plugin worked wonderfully!!!!!. For anyone who has had the problem with updating files becouse they are in use or becouse the application was ran during your update, this is the best fix I have found. I would even reccomend that this be an option on the installer becouse it would help prevent install or update failures. Thanks again for the solution.
Ok, minor bug (with calling any proc(void)) fixed, and GetLastError() option added. Use "?e" at proc specification, and pop first value from stack as getlasterror result.
Here what you want (and update dll and sources please):
Here what you want (and update dll and sources please):
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutex") i .r1 ?e'
pop $0
StrCmp $0 183 0 +3
MessageBox MB_OK "installer already running"
Abort
StrCmp $0 0 done
MessageBox MB_OK "error creating mutex, getlasterror didn't return success"
done: Updated CVS, thanks.
what is "mutex" in detail?
i dont know about ther kernel routines and M$ ist not very useful to me.
i dont know about ther kernel routines and M$ ist not very useful to me.
Well, seems pretty clear to me:
A mutex object is a synchronization object whose state is set to signaled when it is not owned by any thread, and nonsignaled when it is owned. Only one thread at a time can own a mutex object, whose name comes from the fact that it is useful in coordinating mutually exclusive access to a shared resource. For example, to prevent two threads from writing to shared memory at the same time, each thread waits for ownership of a mutex object before executing the code that accesses the memory. After writing to the shared memory, the thread releases the mutex object.Any more details you want to know?
huh?
is it possible to explain it with simple words to me?
What about "myMutex" - that's the object?
is it possible to explain it with simple words to me?
What about "myMutex" - that's the object?
A mutex is a lock. It can be locked by one program so the other can't open it. In our case, your program creates a mutex and locks it. The installer tries to open this mutex, and if it sees that the mutex is locked it concludes that your program is running.
Every mutex has an unique name, in the example above it's "myMutex".
Every mutex has an unique name, in the example above it's "myMutex".
is a "mutex" an option from that program or is it automatically created?
on 1st it not sure that program is really running - or am i wrong?
on 1st it not sure that program is really running - or am i wrong?
Your program has to create a mutex using a function called CreateMutex.
I don't understand the second question, what is unsure and when?
I don't understand the second question, what is unsure and when?
That's very interesting Kichik...
Is it possible to find mutex names (if any) from all applications?
It could be useful if Quake2 (game) is still running when it musn't be..
-Stu
Is it possible to find mutex names (if any) from all applications?
It could be useful if Quake2 (game) is still running when it musn't be..
-Stu
If the application has created a mutex it's possible. All you need to know is the name. Mutexes are global or at least global on the current session (in XP fast-switching or NT terminal services).
Mutexes also have security attributes, so the application can deny you from opening the mutex. But you'll still be able to know the application is there because the mutex exists 🙂
Mutexes also have security attributes, so the application can deny you from opening the mutex. But you'll still be able to know the application is there because the mutex exists 🙂
So, say if the exe or game is called quake2, then the mutex will probably be called quake2 right?
I'll look into this...
Thanks again btw
-Stu
I'll look into this...
Thanks again btw
-Stu
No, that's not a sure thing. Wasn't Quake 2 originally a DOS game? It might not set a mutex at all. Open it using Dependency Walker and see if it calls CreateMutex (under kernel32.dll).
Originally posted by brainsuckerdo I need to destroy the Mutex I create in the .onInit Function or is that done automatically?
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutex") i .r1 ?e' pop $0 StrCmp $0 183 0 +3 MessageBox MB_OK "installer already running" Abort StrCmp $0 0 done MessageBox MB_OK "error creating mutex, getlasterror didn't return success" done:
Vytautas
You can close it using ReleaseMutex / CloseHandle. However, it's not really required, because it will be released when the process has ended.
Originally posted by brainsuckercan you explain what Use "?e" at proc specification means? when i used this code in my script it always went to the error leg. why can't i create the mutex successfully? sorry, i'm very ignorant when it comes to windows API.
Ok, minor bug (with calling any proc(void)) fixed, and GetLastError() option added. Use "?e" at proc specification, and pop first value from stack as getlasterror result.
[/PHP]
?e tells System.dll to return the return value of GetLastError on the stack. It is only available in the latest CVS version, so unless you're using that System.dll will probably fail. Get it using NSIS Update or the nightly snapshot in the NSIS homepage.
Thanks! It worked after i copied the new System.dll.
It seems to me that one would want to use this technique in both .onInit and un.onInit. For example, one's module might control a shared component, and a user might unknowingly think it's okay to uninstall one app using that component while installing another.
But one can't actually use this technique for that purpose, because if you're doing an upgrade, you might have to run the uninstaller before placing the new files, which would mean 2 threads using the same mutex.
Is there a suggested way to handle this?
But one can't actually use this technique for that purpose, because if you're doing an upgrade, you might have to run the uninstaller before placing the new files, which would mean 2 threads using the same mutex.
Is there a suggested way to handle this?
Have the uninstaller create the mutex only if a certain command-line switch was NOT present and have the upgrade installer launch the uninstaller with that switch, but the standard unsinstall shortcuts/entries should launch without the switch.
Vytautas
Vytautas
Do i need the plugins mentioned above on the v2 final ?
No, you only have to use the standard System plug-in.
thx
I'm trying to create a mutex and use the installer on windows 7.
My problem here is that windows 7 always reports that the installer is running, even at the first startup.
This is the code I use:
I would be pleased if someone is able to find out what the problem is here.
Thanks a lot!
My problem here is that windows 7 always reports that the installer is running, even at the first startup.
This is the code I use:
; Allow only one installer instanceMaybe there is something wrong with my code.
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutex") i .r1 ?e'
Pop $R0
StrCmp $R0 0 +3
MessageBox MB_OK "Running"
Quit
I would be pleased if someone is able to find out what the problem is here.
Thanks a lot!
I think it should be "CreateMutexA(i 0, i 0, t "myMutex") i .r0 ?e".
See: http://nsis.sourceforge.net/Allow_on...aller_instance
See: http://nsis.sourceforge.net/Allow_on...aller_instance