|
|
|
|
#1 |
|
Member
Join Date: Apr 2003
Location: Austin, TX
Posts: 61
|
Need Help with Set and Release Mutex!
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 |
|
|
|
|
|
#2 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
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): code: NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#3 |
|
Member
Join Date: Apr 2003
Location: Austin, TX
Posts: 61
|
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 |
|
|
|
|
|
#4 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
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:
code: NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#5 |
|
Member
Join Date: Apr 2003
Location: Austin, TX
Posts: 61
|
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.
|
|
|
|
|
|
#6 |
|
Senior Member
|
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): PHP Code:
|
|
|
|
|
|
#7 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
Updated CVS, thanks.
NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#8 |
|
Major Dude
Join Date: May 2003
Posts: 681
|
what is "mutex" in detail?
i dont know about ther kernel routines and M$ ist not very useful to me. Greets, Brummelchen |
|
|
|
|
|
#9 | |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
Well, seems pretty clear to me:
Quote:
NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
|
#10 |
|
Major Dude
Join Date: May 2003
Posts: 681
|
huh?
is it possible to explain it with simple words to me? What about "myMutex" - that's the object? Greets, Brummelchen |
|
|
|
|
|
#11 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
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". NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#12 |
|
Major Dude
Join Date: May 2003
Posts: 681
|
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? Greets, Brummelchen |
|
|
|
|
|
#13 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
Your program has to create a mutex using a function called CreateMutex.
I don't understand the second question, what is unsure and when? NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#14 |
|
Moderator
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
|
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 |
|
|
|
|
|
#15 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
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
NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#16 |
|
Moderator
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
|
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 |
|
|
|
|
|
#17 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
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).
NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#18 | |
|
Major Dude
|
Quote:
Vytautas |
|
|
|
|
|
|
#19 |
|
NSIS MUI Dev
Join Date: Nov 2001
Posts: 3,717
|
You can close it using ReleaseMutex / CloseHandle. However, it's not really required, because it will be released when the process has ended.
|
|
|
|
|
|
#20 | |
|
Junior Member
Join Date: Nov 2003
Posts: 4
|
Quote:
|
|
|
|
|
|
|
#21 |
|
NSIS MUI Dev
Join Date: Nov 2001
Posts: 3,717
|
|
|
|
|
|
|
#22 |
|
M.I.A.
[NSIS Dev, Mod] Join Date: Oct 2001
Location: Israel
Posts: 11,343
|
?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.
NSIS FAQ | NSIS Home Page | Donate $ "I hear and I forget. I see and I remember. I do and I understand." -- Confucius |
|
|
|
|
|
#23 |
|
Junior Member
Join Date: Nov 2003
Posts: 4
|
Thanks! It worked after i copied the new System.dll.
|
|
|
|
|
|
#24 |
|
Junior Member
Join Date: Jul 2004
Posts: 14
|
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? |
|
|
|
|
|
#25 |
|
Major Dude
|
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 |
|
|
|
|
|
#26 |
|
Major Dude
Join Date: May 2003
Posts: 681
|
Do i need the plugins mentioned above on the v2 final ?
Greets, Brummelchen |
|
|
|
|
|
#27 |
|
NSIS MUI Dev
Join Date: Nov 2001
Posts: 3,717
|
No, you only have to use the standard System plug-in.
|
|
|
|
|
|
#28 |
|
Major Dude
Join Date: May 2003
Posts: 681
|
thx
Greets, Brummelchen |
|
|
|
|
|
#29 | |
|
Junior Member
Join Date: Feb 2008
Posts: 34
|
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: Quote:
I would be pleased if someone is able to find out what the problem is here. Thanks a lot! |
|
|
|
|
|
|
#30 |
|
Major Dude
Join Date: Feb 2007
Posts: 672
|
I think it should be "CreateMutexA(i 0, i 0, t "myMutex") i .r0 ?e".
See: http://nsis.sourceforge.net/Allow_on...aller_instance |
|
|
|
|
|
#31 |
|
Moderator
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
|
I don't think you should use GetLastError (?e) to determine the result of CreateMutex. Instead of i.r0 ?e on the end, just use i.s. The rest of the code can stay the same as CreateMutex will return 0 (NULL) on failure.
Stu |
|
|
|
|
|
#32 | |||
|
Junior Member
Join Date: Feb 2008
Posts: 34
|
Quote:
Quote:
Quote:
Edit: Ah! What I found out is that I'm using the UAC library and because of this the program seems to start twice at the first time - I printed out the message of the return value of createMutex and it appears twice! It may not relate to this topic. I'm going to ask my question in the related plugin topic, so if someone of you got an answer please answer in that topic |
|||
|
|
|
|
|
#33 |
|
Moderator
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
|
Sorry I meant i.s not .s.
Stu |
|
|
|
|
|
#34 |
|
Junior Member
Join Date: Apr 2014
Posts: 3
|
Mutex Inheritance
Hi,
I'm trying to make the Mutex inheritable so that the child process (in this example notepad.exe) will keep it open even though the parent process has exited, here what I have so far: System::Alloc 72 Pop $4 System::Call "*$4(i 72,n,i 1)" # Set bInheritHandle to true System::Call 'Kernel32::CreateMutexA(i r4, i 0, t "Global\ProductName") i.r1?e' System::Free $4 Pop $2 Detailprint $2 StrCmp $2 "0" 0 +2 ExecWait '"notepad.exe"' But I keep getting error 998 (ERROR_NOACCESS) returned. Can anybody help? |
|
|
|
|
|
#35 |
|
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,442
|
sizeof(SECURITY_ATTRIBUTES) = 12 on a 32 bit system? Not sure where you got 72 from. Does it even create the mutex?
I see you are using the Global\ prefix, you might need to set lpSecurityDescriptor in SECURITY_ATTRIBUTES if you want other users to access the mutex. Anyway, ExecWait calls CreateProcess with inherit = false so you need to call CreateProcess yourself with the system plugin... IntOp $PostCount $PostCount + 1 |
|
|
|
|
|
#36 |
|
Junior Member
Join Date: Apr 2014
Posts: 3
|
Thanks! It was the buffer size that was causing the issue, that and I was setting the size with i instead of l.
It works perfectly now across all sessions. |
|
|
|
|
|
#37 |
|
Moderator
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,442
|
i was right, l is 64 bit but you got lucky and it flows over into the field where you just used n and it should probably be i0.
Try this: System::Call "*(i 12,i 0,i 1)i.r4" IntOp $PostCount $PostCount + 1 |
|
|
|
|
|
#38 |
|
Junior Member
Join Date: Apr 2014
Posts: 3
|
Thanks again! That works nicely with the second field set to 0.
|
|
|
|
![]() |
|
|||||||
| Thread Tools | Search this Thread |
| Display Modes | |
|
|