Old 16th April 2003, 17:38   #1
billym
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
billym is offline   Reply With Quote
Old 16th April 2003, 19:39   #2
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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:
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


NSIS FAQ | NSIS Home Page | Donate $
"I hear and I forget. I see and I remember. I do and I understand." -- Confucius
kichik is offline   Reply With Quote
Old 16th April 2003, 21:11   #3
billym
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
billym is offline   Reply With Quote
Old 17th April 2003, 10:41   #4
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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:
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

Attached Files
File Type: zip mutex.zip (3.0 KB, 409 views)

NSIS FAQ | NSIS Home Page | Donate $
"I hear and I forget. I see and I remember. I do and I understand." -- Confucius
kichik is offline   Reply With Quote
Old 17th April 2003, 14:29   #5
billym
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.
billym is offline   Reply With Quote
Old 17th April 2003, 20:20   #6
brainsucker
Senior Member
 
brainsucker's Avatar
 
Join Date: Sep 2002
Location: Minsk, Belarus
Posts: 190
Send a message via ICQ to brainsucker
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:
  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
Attached Files
File Type: zip system.zip (17.4 KB, 357 views)
brainsucker is offline   Reply With Quote
Old 18th April 2003, 11:20   #7
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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
kichik is offline   Reply With Quote
Old 8th July 2003, 12:36   #8
Brummelchen
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
Brummelchen is offline   Reply With Quote
Old 8th July 2003, 12:44   #9
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
Join Date: Oct 2001
Location: Israel
Posts: 11,343
Well, seems pretty clear to me:

Quote:
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?

NSIS FAQ | NSIS Home Page | Donate $
"I hear and I forget. I see and I remember. I do and I understand." -- Confucius
kichik is offline   Reply With Quote
Old 8th July 2003, 13:31   #10
Brummelchen
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
Brummelchen is offline   Reply With Quote
Old 8th July 2003, 13:41   #11
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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
kichik is offline   Reply With Quote
Old 8th July 2003, 13:46   #12
Brummelchen
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
Brummelchen is offline   Reply With Quote
Old 8th July 2003, 13:51   #13
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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
kichik is offline   Reply With Quote
Old 8th July 2003, 16:47   #14
Afrow UK
Moderator
 
Afrow UK's Avatar
 
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
Afrow UK is offline   Reply With Quote
Old 8th July 2003, 16:51   #15
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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
kichik is offline   Reply With Quote
Old 8th July 2003, 17:15   #16
Afrow UK
Moderator
 
Afrow UK's Avatar
 
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
Afrow UK is offline   Reply With Quote
Old 9th July 2003, 11:21   #17
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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
kichik is offline   Reply With Quote
Old 18th September 2003, 04:40   #18
Vytautas
Major Dude
 
Vytautas's Avatar
 
Join Date: May 2003
Location: Victoria, Australia
Posts: 643
Send a message via ICQ to Vytautas
Quote:
Originally posted by brainsucker
PHP Code:
  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
do I need to destroy the Mutex I create in the .onInit Function or is that done automatically?

Vytautas
Vytautas is offline   Reply With Quote
Old 18th September 2003, 12:43   #19
Joost Verburg
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.
Joost Verburg is offline   Reply With Quote
Old 14th November 2003, 18:04   #20
putty
Junior Member
 
Join Date: Nov 2003
Posts: 4
Quote:
Originally posted by brainsucker
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]
can 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.
putty is offline   Reply With Quote
Old 14th November 2003, 18:07   #21
Joost Verburg
NSIS MUI Dev
 
Join Date: Nov 2001
Posts: 3,717
Tried this code?

http://nsis.sourceforge.net/site/ind...&tx_faq_faq=29
Joost Verburg is offline   Reply With Quote
Old 14th November 2003, 18:08   #22
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
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
kichik is offline   Reply With Quote
Old 14th November 2003, 19:55   #23
putty
Junior Member
 
Join Date: Nov 2003
Posts: 4
Thanks! It worked after i copied the new System.dll.
putty is offline   Reply With Quote
Old 12th July 2004, 22:11   #24
dpbluegreen
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?
dpbluegreen is offline   Reply With Quote
Old 12th July 2004, 22:48   #25
Vytautas
Major Dude
 
Vytautas's Avatar
 
Join Date: May 2003
Location: Victoria, Australia
Posts: 643
Send a message via ICQ to Vytautas
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 is offline   Reply With Quote
Old 13th July 2004, 10:48   #26
Brummelchen
Major Dude
 
Join Date: May 2003
Posts: 681
Do i need the plugins mentioned above on the v2 final ?

Greets, Brummelchen
Brummelchen is offline   Reply With Quote
Old 13th July 2004, 12:06   #27
Joost Verburg
NSIS MUI Dev
 
Join Date: Nov 2001
Posts: 3,717
No, you only have to use the standard System plug-in.
Joost Verburg is offline   Reply With Quote
Old 13th July 2004, 13:44   #28
Brummelchen
Major Dude
 
Join Date: May 2003
Posts: 681
thx

Greets, Brummelchen
Brummelchen is offline   Reply With Quote
Old 9th May 2011, 06:17   #29
klopfdreh
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:
; Allow only one installer instance
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutex") i .r1 ?e'
Pop $R0
StrCmp $R0 0 +3
MessageBox MB_OK "Running"
Quit
Maybe there is something wrong with my code.

I would be pleased if someone is able to find out what the problem is here.

Thanks a lot!
klopfdreh is offline   Reply With Quote
Old 9th May 2011, 08:38   #30
jpderuiter
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
jpderuiter is offline   Reply With Quote
Old 9th May 2011, 16:13   #31
Afrow UK
Moderator
 
Afrow UK's Avatar
 
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
Afrow UK is offline   Reply With Quote
Old 10th May 2011, 06:11   #32
klopfdreh
Junior Member
 
Join Date: Feb 2008
Posts: 34
Quote:
I think it should be "CreateMutexA(i 0, i 0, t "myMutex") i .r0 ?e".
See: http://nsis.sourceforge.net/Allow_on...aller_instance
This doesn't work for me either

Quote:
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 .s. The rest of the code can stay the same as CreateMutex will return 0 (NULL) on failure.
I used the following code to check out .s:
Quote:
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutex") .s'
But this time the CreateMutex results in nothing - not even a number. I tested it with MessageBox MB_OK $R0

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
klopfdreh is offline   Reply With Quote
Old 10th May 2011, 10:13   #33
Afrow UK
Moderator
 
Afrow UK's Avatar
 
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
Sorry I meant i.s not .s.

Stu
Afrow UK is offline   Reply With Quote
Old 3rd April 2014, 16:27   #34
Xokar7
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?
Xokar7 is offline   Reply With Quote
Old 3rd April 2014, 19:58   #35
Anders
Moderator
 
Anders's Avatar
 
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
Anders is offline   Reply With Quote
Old 4th April 2014, 10:15   #36
Xokar7
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.
Xokar7 is offline   Reply With Quote
Old 4th April 2014, 14:21   #37
Anders
Moderator
 
Anders's Avatar
 
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
Anders is offline   Reply With Quote
Old 4th April 2014, 15:36   #38
Xokar7
Junior Member
 
Join Date: Apr 2014
Posts: 3
Smile

Thanks again! That works nicely with the second field set to 0.
Xokar7 is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump