- NSIS Discussion
- Help with ReleaseMutex
Archive: Help with ReleaseMutex
Clammerz
21st December 2006 16:45 UTC
Help with ReleaseMutex
Hi, I was wondering if anyone could advise me on how to go about using this API call.
BOOL WINAPI ReleaseMutex(
HANDLE hMutex
);
I have a macro, provided by the wiki pages:
!macro MutexCheck _mutexname _outvar
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}") i .${_outvar} ?e'
pop ${_outvar}
!macroend
Upon reading the
"Synchronization Object Security and Access Rights" page on MSDN, I noticed this:
MUTEX_MODIFY_STATE (0x0001) Modify state access, which is required for the ReleaseMutex function.
I need to change my macro to include this? So that the installer can modify it?
I'm also not exactly sure how to get the Handle of the Mutex. I'm guessing it's not simply it's name right?
The reason I want to release the Mutex, is that my installer creates two mutex's. One identical to the game I'm trying to patch (so they cannot run the game while trying to patch), and one of it's own, so the user can't run it twice. (reason there being two is that I can set a specific message depending on what the situation is.)
Anyways. At the finish page, I have the option to lauch said game I'm patching. The game won't lauch if it loads faster than the installer can close itself (almost always). So I want to release the Mutex in my Finish Page preFunction.
Thank you very much for your time in reading this.
Red Wine
21st December 2006 17:09 UTC
There is a plugin at wiki http://nsis.sourceforge.net/CreateMutex_plug-in that might be helpful.
Clammerz
21st December 2006 20:12 UTC
Unfortunately that plug-in only deals with the creation of a mutex. Not releasing one.
Maybe I wasn't direct enough in my first post, I apologise.
What I am after is a basic example of how to use the ReleaseMutex API call using the System plug-in. And also if I need to modify the existing Macro to allow for permissions to release it.
Thank you for your assistance : )
Red Wine
21st December 2006 20:31 UTC
You're welcome!
Just found this forum thread.
http://forums.winamp.com/showthread....hreadid=131968
I hope that should be helpful.
Clammerz
22nd December 2006 02:55 UTC
Ah, I also came across that thread during my search. While it seemed promising from the title, after the user found out how to create the Mutex, they didn't bother discussing anything further on how to release it. Hee hee~
I guess all the System/API guru's are on holiday at the moment? : (
Oh well, I might have to remove the 'run' tickbox at the end.
Thanks again for your reply.
demiller9
22nd December 2006 05:53 UTC
The MSDN page for CreateMutex says the return value is the mutex handle. The macro you have is storing the handle (the return code) in _outvar, but then pops the System::Call return code from GetLastError into the same variable. I suggest changing the macro to put the handle into its own variable:
!macro MutexCheck _mutexname _outvar hMutex
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}") i .${_hMutex} ?e'
pop ${_outvar}
!macroend
And use it something like this:
!insertmacro MutexCheck "myMutex" $0 $1
intCmp $1 0 MutexError
...
System::Call 'kernel32::ReleaseMutexA(i $1) i.r0'
IntCmp $0 0 MutexError2
Don
Mr Inches
22nd December 2006 07:01 UTC
Don't forget to use CloseHandle on the mutex when you are done with it - Windows won't destroy it until all processes that have an open handle on the mutex close it.
While it is true that Windows will clean up when the process exits, relying on this is really a sign of poor code; you should always clean up your own resources explicitly.
Duncan
Clammerz
22nd December 2006 10:27 UTC
Thank you all very much for your replies!
Here is what I have so far:
Macro:
!macro MutexCheck _mutexname _outvar _hMutex
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}") i .${_hMutex} ?e'
pop ${_outvar}
!macroend
Usage:
!insertmacro MutexCheck "${MyMutexName}" $0 $9
StrCpy $MutexHandle $9
StrCmp $0 0 launch
StrLen $0 "$(^Name)"
IntOp $0 $0 + 1
loop:
FindWindow $1 '#32770' '' 0 $1
IntCmp $1 0 +4
System::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
StrCmp $2 "$(^Name)" 0 loop
System::Call "user32::SetForegroundWindow(i r1) i."
Abort
launch:
Release:
System::Call 'kernel32::ReleaseMutexA(i $MutexHandle) i.r0'
MessageBox MB_OK "Unlocked. Return: $0"
MessageBox is displaying "Return: error"
Hmm, when I use...
System::Call 'kernel32::CloseHandle(i $MutexHandle) i.r0'
MessageBox MB_OK "Unlocked. Return: $0"
It returns 0, but still doesn't lat me lauch.
Does the loop have something to do with it?
kichik
22nd December 2006 12:02 UTC
Your MutexCheck macro has syntax errors. i.$$0 is not a valid parameter definition for the System plug-in. You should pass i.r0 instead.
Clammerz
22nd December 2006 19:50 UTC
Thanks kichik for your reply.
I was wondering if you could explain a little further about my error.
Sorry to say, but I'm still pretty green on the System plug-in, API calls, and the using the internal NSIS stack itself.
I'm not sure how you are getting i.$$0
Is that from "i .${_hMutex}" ?
I've tried many other arrangements, and I'm still not able to get it working. I even stripped everything down to the very basics:
System
::Call 'kernel32::CreateMutexA(i 0, i 0, t "${MyMutexName}") i.r0 ?e'
>Pop $0
StrCpy $MutexHandle$0
StrCmp$0 0 launch
MessageBox MB_OK "Mutant inuse"
Abort
launch:
>MessageBox MB_OK "Mutex open"
>System::Call 'kernel32::ReleaseMutexA(i $MutexHandle) i.r0'
>MessageBox MB_OK "Mutex released. Return: $0"
This is very puzzling for me, as I'm really not sure what's going on.
It is returning error. Is that because I'm using invalid parameter definition?
Or is it because I need to change the default security settings of the Mutext itself?
Thank you again for your time.
kichik
23rd December 2006 03:47 UTC
It was supposed to be just `i.$0`, I had a typo. System plug-in parameters are divided into three - type, input and output. When you use $0 for the output, the actual value of $0 will be copied into there and you'll eventually get something like `i.123`. This doesn't tell System where to put the value it gets, it tells it what value to put there. You must tell it in which register you want to put the value, and that can only be done with `r*`.
You also have another error there, where the type is wrong. It's a pointer to an integer, not an integer. Use an asterisk before the `i`.
For more information, read the System manual, it has a few step by step guides and some examples.
Clammerz
23rd December 2006 12:58 UTC
Thank you kichik.
I finally got it working : )
Here's a snippet if anyone else is having any issues with it:
"MutexNameHere"
>!macro MutexCheck _mutexname _outvar _handle
System
::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}" ) i.r1 ?e'
>StrCpy ${_handle} $1
Pop${_outvar}
!macroend
>Function .onInit
>!insertmacro MutexCheck "${MyMutexName}" $0 $9
StrCmp$0 0 launch
StrLen$0 "$(^Name)"
IntOp $0 $0 + 1
loop:
FindWindow $1 '#32770' '' 0 $1
StrCmp$1 0 +1 +2
IntOp$3 $3 + 1
IntCmp$3 3 +5
System::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
StrCmp $2 "$(^Name)" 0 loop
System::Call "user32::SetForegroundWindow(i r1) i."
System::Call "user32::ShowWindow(i r1,i 9) i."
Abort
launch:
!insertmacro MutexCheck "GameMutexHere" $0 $MutexHandle
StrCmp$0 0 launchB
StrLen$0 "GameWindowNameHere"
IntOp $0 $0 + 1
loopB:
FindWindow $1 ***91;"ClassHere"***93; ***91;"GameWindowNameHere"***93; ""
IntCmp $1 0 +3
System::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
StrCmp $2 "GameWindowNameHere" 0 loopB
MessageBox MB_OK|MB_ICONEXCLAMATION "Please close Game before continuing."
System::Call "user32::SetForegroundWindow(i r1) i."
System::Call "user32::ShowWindow(i r1,i 9) i."
Abort
launchB:
>FunctionEnd
>Function "PreFinishFunc" ;Finish Page 'pre_function'
>System::Call 'kernel32::CloseHandle(i $MutexHandle) i.'
>FunctionEnd
>
Also, for some strange reason, when using FindWindow, and the '#32770' class, it was returning *every* result before my installer. Even 'console', and '0' ?
So I had to put in a little counter of sorts, to let it find 0 once before skipping ahead to the abort.
As you can see, I'm not the neatest, or most innovative scripter about, so don't expect anything special : P
Thanks once again for everyone's help.
Comm@nder21
23rd December 2006 16:08 UTC
sorry, small question:
what do you need "ReleaseMutex" for? :)
i never used it, because every mutex my installers create on startup seem to be released automatically with their shutdown again.
{_trueparuex^}
23rd December 2006 18:16 UTC
Originally posted by Comm@nder21
sorry, small question:
what do you need "ReleaseMutex" for? :)
i never used it, because every mutex my installers create on startup seem to be released automatically with their shutdown again.
It's in the first post. :p
Comm@nder21
24th December 2006 12:42 UTC
ah, read it!
sounds reasonable :)