DarkMatter Posted May 8, 2008 Posted May 8, 2008 Here is what I am trying to do:Script2 runs and I want Script1 to wait until Script2 is complete before it continues with execution. I know I could just use ProcessExists() to do this but the problem is the compiled name will be diffrent 99% of the time so I was just going to have my apps create a mutex and watch for that mutex to go away.The problem is when Script2 closes after 3 seconds. Script 1 is still seeing the mutex. Any ideas?Here is the code:Script1CheckWDTCode() MsgBox(0,0,"Mutex Not Found") Func CheckWDTCode() $MutexName = StringReplace("WDTCodeRunning", "\", "") Local $handle = DllCall("kernel32.dll", "int", "CreateMutex", "int", 0, "long", 1, "str", $MutexName) Local $lastError = DllCall("kernel32.dll", "int", "GetLastError") If $lastError[0] = 183 Then ConsoleWrite("Mutex Found" & @CRLF) Sleep(1500) CheckWDTCode() EndIf EndFuncScript2CheckWDTCode() Sleep(3000) Func CheckWDTCode() $MutexName = StringReplace("WDTCodeRunning", "\", "") Local $handle = DllCall("kernel32.dll", "int", "CreateMutex", "int", 0, "long", 1, "str", $MutexName) Local $lastError = DllCall("kernel32.dll", "int", "GetLastError") If $lastError[0] = 183 Then Sleep(1500) CheckWDTCode() EndIf EndFunc [sub]Quantum mechanics: The dreams stuff is made of[/sub]
John Posted May 8, 2008 Posted May 8, 2008 (edited) Use WinWaitNotActive(). It uses the windows title not the program name, so even if you rename the exe it still works. Doh.. WinExists() Edited May 8, 2008 by John
DarkMatter Posted May 8, 2008 Author Posted May 8, 2008 Use WinWaitNotActive(). It uses the windows title not the program name, so even if you rename the exe it still works.Doh.. WinExists()Not looking for a distinct window name. This will be multiple scripts, multiple exes. [sub]Quantum mechanics: The dreams stuff is made of[/sub]
John Posted May 8, 2008 Posted May 8, 2008 You can use WinSetTitle() to a certain text if the program has thread control then switch it back when released. This method wouldn't even require the program to actually exit, though it could change title before exiting. The title would just be a flag that determined thread ownership and all other scripts must wait on it to clear.
DarkMatter Posted May 8, 2008 Author Posted May 8, 2008 You can use WinSetTitle() to a certain text if the program has thread control then switch it back when released. This method wouldn't even require the program to actually exit, though it could change title before exiting. The title would just be a flag that determined thread ownership and all other scripts must wait on it to clear.Okay... Thats an idea, but I can not do that. This is for an enterprise solution with multiple devs creating install packages. I am working on a function that they would add in their scripts that would create a mutex. That way, only one script will run at a time... (Basically an installation monitor for dev created packages.) [sub]Quantum mechanics: The dreams stuff is made of[/sub]
John Posted May 8, 2008 Posted May 8, 2008 That definately complicates the situation. If it's a function they must add to their script it could still be made to work. Although I'm not sure of you particular situation. You could also create a script they must call to execute their script. Your script would simply take the command line and run their script for them. Your script would then know what process to wait on to exit before it exited. In the meantime it would just loop a wait state. It wouldn't be the Dev script other scripts must wait on but the script needed to run it. I made a media player implementation that did something similar. When it was playing a movie and another instance tried to open it would add that new movie to a que in a config file and exit. When the first instance finshed it automatically played the second movie and so on.
DarkMatter Posted May 8, 2008 Author Posted May 8, 2008 I could do that, but that would complicate matters in this environment. Does anyone know why the mutex is not releasing? [sub]Quantum mechanics: The dreams stuff is made of[/sub]
John Posted May 8, 2008 Posted May 8, 2008 (edited) You must call ReleaseMutex().http://msdn.microsoft.com/en-us/library/ms685066(VS.85).aspxUsing Mutex Objectshttp://msdn.microsoft.com/en-us/library/ms686927(VS.85).aspxETA: There is also a WAIT_ABANDONED flag you can check for and take ownership of an abandoned mutex.http://blogs.msdn.com/oldnewthing/archive/.../12/463977.aspx Edited May 8, 2008 by John
DarkMatter Posted May 8, 2008 Author Posted May 8, 2008 This is what I am doing: Opt("OnExitFunc", "ExitScript") Dim $MutexHandle CheckWDTCode() MsgBox(0,0,"Mutex Not Found") Func CheckWDTCode() $MutexName = StringReplace("WDTCodeRunning", "\", "") Local $dll = DllOpen("kernel32.dll") $MutexHandle = DllCall($dll, "long", "CreateMutexA", "ptr", 0, "int", 1, "str", $MutexName) Local $lastError = DllCall($dll, "int", "GetLastError") DllClose($dll) If $lastError[0] = 183 Then ConsoleWrite("Mutex Found" & @CRLF) Sleep(1500) CheckWDTCode() EndIf EndFunc Func ExitScript() DllCall("kernel32.dll", "int", "ReleaseMutex", "hwnd", $MutexHandle[1]) EndFunc The Mutex is still not Releasing. [sub]Quantum mechanics: The dreams stuff is made of[/sub]
DarkMatter Posted May 8, 2008 Author Posted May 8, 2008 Singleton will close the script. I need the script to loop until that mutex is closed. [sub]Quantum mechanics: The dreams stuff is made of[/sub]
Moderators SmOke_N Posted May 8, 2008 Moderators Posted May 8, 2008 Singleton will close the script. I need the script to loop until that mutex is closed._SingleTon will close the script if you use that option. You will see that _SingleTon in fact uses the CreateMutex method as well.OnExit you will need to release the Mutex as described above. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
DarkMatter Posted May 8, 2008 Author Posted May 8, 2008 That is basically where I got the code from. But for some reason when the two scripts are running, script1 watching the mutex script2 creating it, when script 2 closes and calles the ReleaseMutex funtion, the mutex does not clear until the first script closes as well. [sub]Quantum mechanics: The dreams stuff is made of[/sub]
Moderators SmOke_N Posted May 8, 2008 Moderators Posted May 8, 2008 (edited) That is basically where I got the code from. But for some reason when the two scripts are running, script1 watching the mutex script2 creating it, when script 2 closes and calles the ReleaseMutex funtion, the mutex does not clear until the first script closes as well.Playing around with it:Global $hMutexGlobal ConsoleWrite("Mutex exists: " & (_MutexExists("WDTCodeRunning") = 1) & @CRLF) $hMutexGlobal = _CreateMutex("WDTCodeRunning") ConsoleWrite("Mutex Handle: " & $hMutexGlobal & @CRLF) ConsoleWrite("Mutex exists: " & (_MutexExists("WDTCodeRunning") = 1) & @CRLF) ConsoleWrite("Mutex Released: " & (_ReleaseMutex($hMutexGlobal) = 1) & @CRLF) ConsoleWrite("Mutex exists: " & (_MutexExists("WDTCodeRunning") = 1) & @CRLF) Func _MutexExists($szMutexName) Local $hMutex = DllCall("Kernel32.dll", "hwnd", "OpenMutex", "int", 0x1F0001, "int", 1, "str", $szMutexName) Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError") If IsArray($aGLE) And $aGLE[0] = 127 Then Return 1 Return 0 EndFunc ;==>_MutexExists Func _CreateMutex($szMutexName) Local $hMutex = DllCall("Kernel32.dll", "hwnd", "CreateMutex", "ptr", 0, "int", 1, "str", $szMutexName) Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError") If $aGLE[0] = 183 Then Return 0 Return $hMutex[0] EndFunc ;==>_CreateMutex Func _ReleaseMutex($hMutex) Local $aRM = DllCall("kernel32.dll", "int", "ReleaseMutex", "hwnd", $hMutex) If IsArray($aRM) And $aRM[0] > 0 Then Return 1 Return 0 EndFunc ;==>ExitScriptThis might make it easier to figure out what you need. I wouldn't loop inside functions with a recursive call, just do While condition etc... outside of it. I'll look a bit more to see if I can figure out why it is releasing but still showing. Edited May 8, 2008 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
Moderators SmOke_N Posted May 8, 2008 Moderators Posted May 8, 2008 (edited) Here, this seems to work:Global $hMutexGlobal ConsoleWrite("Mutex exists: " & (_MutexExists("WDTCodeRunning") = 1) & @CRLF) $hMutexGlobal = _CreateMutex("WDTCodeRunning") ConsoleWrite("Mutex Handle: " & $hMutexGlobal & @CRLF) ConsoleWrite("Mutex exists: " & (_MutexExists("WDTCodeRunning") = 1) & @CRLF) ConsoleWrite("Mutex Released: " & (_ReleaseMutex($hMutexGlobal) = 1) & @CRLF) ConsoleWrite("Mutex exists: " & (_MutexExists("WDTCodeRunning") = 1) & @CRLF) Func _MutexExists($szMutexName) Local $hMutex = DllCall("Kernel32.dll", "hwnd", "OpenMutex", "int", 0x1F0001, "int", 1, "str", $szMutexName) Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError") If IsArray($hMutex) And $hMutex[0] Then DllCall("Kernel32.dll", "int", "CloseHandle", "hwnd", $hMutex[0]) EndIf If IsArray($aGLE) And $aGLE[0] = 127 Then Return 1 Return 0 EndFunc ;==>_MutexExists Func _CreateMutex($szMutexName) Local $hMutex = DllCall("Kernel32.dll", "hwnd", "CreateMutex", "ptr", 0, "int", 1, "str", $szMutexName) Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError") If (IsArray($hMutex) = 0) Or (IsArray($aGLE) And $aGLE[0] = 183) Then Return 0 Return $hMutex[0] EndFunc ;==>_CreateMutex Func _ReleaseMutex($hMutex) Local $aRM = DllCall("kernel32.dll", "int", "ReleaseMutex", "hwnd", $hMutex) Local $aCH = DllCall("Kernel32.dll", "int", "CloseHandle", "hwnd", $hMutex) If (IsArray($aRM) And $aRM[0] > 0) And (IsArray($aCH) And $aCH[0] > 0) Then Return 1 Return 0 EndFunc ;==>ExitScript Edited May 8, 2008 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
PsaltyDS Posted May 8, 2008 Posted May 8, 2008 Singleton will close the script. I need the script to loop until that mutex is closed. No, it only exits the script if you elect to do that with the second parameter. _Singleton($sOccurenceName[, $iFlag = 0]) $iFlag 0 - Exit if occurrence already exists (default) 1 - Return if occurrence already exists 2 - Allow the object to be accessed by anybody in the system. This is useful if specifying a "Global\" object in a multi-user environment. You seem to have ignored what SmOke_N told you to begin with -- If you set the second parameter correctly (i.e. 1 - read the help file!) _Singleton() will only return True or False, and could be run in a loop until it received True (only one instance running). Did I miss something special about your circumstances? Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Moderators SmOke_N Posted May 8, 2008 Moderators Posted May 8, 2008 No, it only exits the script if you elect to do that with the second parameter. You seem to have ignored what SmOke_N told you to begin with -- If you set the second parameter correctly (i.e. 1 - read the help file!) _Singleton() will only return True or False, and could be run in a loop until it received True (only one instance running). Did I miss something special about your circumstances? I can see it being handy to create your own mutex for this issue. Since _SingleTon does not return the handle of the Mutex created, only a boolean, there's no way to close the handle until you exit the app and AutoIt does it for you. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
DarkMatter Posted May 8, 2008 Author Posted May 8, 2008 Awesome! Thats what I was looking for. Thanks!!! [sub]Quantum mechanics: The dreams stuff is made of[/sub]
PsaltyDS Posted May 8, 2008 Posted May 8, 2008 I can see it being handy to create your own mutex for this issue. Since _SingleTon does not return the handle of the Mutex created, only a boolean, there's no way to close the handle until you exit the app and AutoIt does it for you.I see what you mean, I think. I'm pretty sure the whole point of how _Singleton() works is that only one Mutex is created, no matter how many instances are running. All instances after the first detect their status by the FAILURE to create another Mutex with the same name. This means if there are three or more instances running, then when the first instance closes, the next remaining instance will succeed in creating the Mutex and return True from _Singleton(), even if there are still other instances running.When I get a chance I'll test that with a demo script.Learning something new every day... Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Moderators SmOke_N Posted May 8, 2008 Moderators Posted May 8, 2008 (edited) I see what you mean, I think. I'm pretty sure the whole point of how _Singleton() works is that only one Mutex is created, no matter how many instances are running. All instances after the first detect their status by the FAILURE to create another Mutex with the same name. This means if there are three or more instances running, then when the first instance closes, the next remaining instance will succeed in creating the Mutex and return True from _Singleton(), even if there are still other instances running. When I get a chance I'll test that with a demo script. Learning something new every day... If that's how it is intended, that's not how it's written: expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name...........: _Singleton ; Description ...: Check if no other occurence is running ; Syntax.........: _Singleton($sOccurenceName[, $iFlag = 0]) ; Parameters ....: $sOccurenceName - String to identify the occurrence of the script. This string may not contain any \ characters unless you are placing the object in a namespace. ; $iFlag - Action if @error ; |0 - Exit if occurrence already exists ; |1 - Return if occurrence already exists ; |2 - Allow the object to be accessed by anybody in the system. This is useful if specifying a "Global\" object in a multi-user environment. ; Return values .: Success - 1 ; Failure - 0 ; Author ........: Valik ; Modified.......: ; Remarks .......: You can place the object in a namespace by prefixing your object name with either "Global\" or "Local\". "Global\" objects combined with the flag 2 are useful in multi-user environments. ; Related .......: ; Link ..........; ; Example .......; Yes ; =============================================================================================================================== Func _Singleton($sOccurenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 Local Const $SECURITY_DESCRIPTOR_REVISION = 1 Local $handle, $lastError, $pSecurityAttributes = 0 If BitAND($iFlag, 2) Then ; The size of SECURITY_DESCRIPTOR is 20 bytes. We just ; need a block of memory the right size, we aren't going to ; access any members directly so it's not important what ; the members are, just that the total size is correct. Local $structSecurityDescriptor = DllStructCreate("dword[5]") Local $pSecurityDescriptor = DllStructGetPtr($structSecurityDescriptor) ; Initialize the security descriptor. Local $aRet = DllCall("advapi32.dll", "int", "InitializeSecurityDescriptor", _ "ptr", $pSecurityDescriptor, "dword", $SECURITY_DESCRIPTOR_REVISION) If Not @error And $aRet[0] Then ; Add the NULL DACL specifying access to everybody. $aRet = DllCall("advapi32.dll", "int", "SetSecurityDescriptorDacl", _ "ptr", $pSecurityDescriptor, "int", 1, "ptr", 0, "int", 0) If Not @error And $aRet[0] Then ; Create a SECURITY_ATTRIBUTES structure. Local $structSecurityAttributes = DllStructCreate("dword;ptr;int") ; Assign the members. DllStructSetData($structSecurityAttributes, 1, DllStructGetSize($structSecurityAttributes)) DllStructSetData($structSecurityAttributes, 2, $pSecurityDescriptor) DllStructSetData($structSecurityAttributes, 3, 0) ; Everything went okay so update our pointer to point to our structure. $pSecurityAttributes = DllStructGetPtr($structSecurityAttributes) EndIf EndIf EndIf $handle = DllCall("kernel32.dll", "int", "CreateMutex", "ptr", $pSecurityAttributes, "long", 1, "str", $sOccurenceName) $lastError = DllCall("kernel32.dll", "int", "GetLastError") If $lastError[0] = $ERROR_ALREADY_EXISTS Then If BitAND($iFlag, 1) Then Return SetError($lastError[0], $lastError[0], 0) Else Exit -1 EndIf EndIf Return $handle[0] EndFunc ;==>_Singleton Edited May 8, 2008 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now