Valik Posted October 7, 2004 Posted October 7, 2004 Thanks to DllCall(), the proper way of only allowing a single instance of a script to run is now possible. Here is the code: Func Singleton($semaphore) Local $ERROR_ALREADY_EXISTS = 183 DllCall("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $semaphore) Local $lastError = DllCall("kernel32.dll", "int", "GetLastError") If $lastError[0] = $ERROR_ALREADY_EXISTS Then Exit -1 EndFunc; Singleton() Once a semaphore is created, a second attemp to create it will result in ERROR_ALREADY_EXISTS. By checking for that error, you know that an instance is already running. The main advantage to this over changing the window title is that its a lot harder to spoof or accidentally trigger since the semaphore is more likely to be completely unique than a window title. It also means the internal window title can be used for whatever purpose the scripter desires. The parameter this function takes should be unique, but not generated randomly. It must be the same between all versions of the script, but it must be different from any other scripts. The longer and more random it is, the less likely to conflict with anything else (But again, it can't be randomly generated at run-time or it will defeat the purpose).
ezzetabi Posted October 8, 2004 Posted October 8, 2004 I'd like to use this but I can't make it work... I tested with this simple script: Sleep(10000) Func OnAutoItStart() SingleTon(@ScriptFullPath) EndFunc ;==>OnAutoItStart Func SingleTon($SEMAPHORE) Local $ERROR_ALREADY_EXISTS = 183 DllCall ("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $SEMAPHORE) Local $LASTERROR = DllCall ("kernel32.dll", "int", "GetLastError") If $LASTERROR[0] = $ERROR_ALREADY_EXISTS Then Exit -1 EndFunc ;==>Singleton but starting on the .au3 icon many times, manys A appear in the tray for the 10 seconds. Moreover putting a MsgBox(0,'',$LASTERROR[0]) before the If/Then shows always 126. What am I doing wrong? If it can help I am using Windows XP 5.1.2600 Sp2
Valik Posted October 8, 2004 Author Posted October 8, 2004 (edited) ezzetabi... @ScriptFullName IS NOT STATIC. Moving the script will change this value, thus, a new Semaphore will be created, thus, two instances will exist. Static means static, as in, never ever will change in any version of the script since the beginning of time until the end of time, regardless of the name of the file or the location of the file on the file system. It can't be influenced by outside forces. Singleton("The name of my project")orSingleton("askdfgjdksjfdskdjfs")Something like that (I use project names without version number).That all being said, attempting to use @ScriptFullPath is also why its not working. Even though the path is a constant string and is less than _MAX_PATH (A requirement of CreateSemaphore), it still doesn't seem to want to use it as the name of the Semaphore.Basically, though, it boils down to incorrect usage of the function. Use it correctly and it works correctly.Edit: Added a little text. Edited October 8, 2004 by Valik
Matt @ MPCS Posted October 8, 2004 Posted October 8, 2004 ezzetabi... @ScriptFullName IS NOT STATIC. Moving the script will change this value, thus, a new Semaphore will be created, thus, two instances will exist. Static means static, as in, never ever will change in any version of the script since the beginning of time until the end of time. Singleton("The name of my project")Something like that (I use project names without version number).That all being said, attempting to use @ScriptFullPath is also why its not working. Even though the path is a constant string and is less than _MAX_PATH (A requirement of CreateSemaphore), it still doesn't seem to want to use it as the name of the Semaphore.Basically, though, it boils down to incorrect usage of the function. Use it correctly and it works correctly.<{POST_SNAPBACK}>I see where you are coming from on it being static, but is there a way to check if the string passed is a literal? If there is then that may be something you would require to avoid this confusion, if not then I would at least note it in documentation. Great UDF though! *** Matt @ MPCS
Valik Posted October 8, 2004 Author Posted October 8, 2004 I see where you are coming from on it being static, but is there a way to check if the string passed is a literal? If there is then that may be something you would require to avoid this confusion, if not then I would at least note it in documentation. Great UDF though! *** Matt @ MPCS<{POST_SNAPBACK}>I wish there was Matt, but I thought I explained myself clearly enough when I said:The parameter this function takes should be unique, but not generated randomly. It must be the same between all versions of the script, but it must be different from any other scripts. The longer and more random it is, the less likely to conflict with anything else (But again, it can't be randomly generated at run-time or it will defeat the purpose).
Matt @ MPCS Posted October 8, 2004 Posted October 8, 2004 I wish there was Matt, but I thought I explained myself clearly enough when I said:<{POST_SNAPBACK}>I see how you would think that it is covered, in fact I almost answered ezzetabi's question because I was thinking the same thing. It seems obvious that it isn't as clear to others as it is to you and me. *** Matt @ MPCS
Greenseed Posted October 8, 2004 Posted October 8, 2004 a little question. on a terminal server with client wan to open the same script at same time. the kernel will respond the error ? and the second script will not openthat righr ... or the user got access of a copie for himself of the kernel32.dll i don't think soo! and if the respond is yes how to make one work. with dllcall fucntion? thx GreenseedMCSE+I, CCNA, A+Canada, QuebecMake Love Around You.
Valik Posted October 8, 2004 Author Posted October 8, 2004 a little question. on a terminal server with client wan to open the same script at same time. the kernel will respond the error ? and the second script will not openthat righr ... or the user got access of a copie for himself of the kernel32.dll i don't think soo! and if the respond is yes how to make one work. with dllcall fucntion? thx<{POST_SNAPBACK}>I have no clue what you are asking or trying to say...
Valik Posted October 8, 2004 Author Posted October 8, 2004 Oh, ezzetabi, I finally see it in the documentation for CreateSemaphore. The backslash is an illegal character in a Semaphore name, which is why @ScriptFullPath fails as a valid Semaphore name; the path contains backslashes.
ezzetabi Posted October 8, 2004 Posted October 8, 2004 Unpleasant as usual Valik. This second answer have a meaning since I was using @scriptfullpath because I created a script that works in its folder and its subfolders, but I wanted to use it at the same time other copies in other folders. Indeed, I have nothing agaist you, but you should think that others people are not always clueless AND stupid AND do not read as you seems to think. Btw, I also tried: Sleep(10000) Func OnAutoItStart() SingleTon('abcabc') EndFunc ;==>OnAutoItStart Func SingleTon($SEMAPHORE) Local $ERROR_ALREADY_EXISTS = 183 DllCall ("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $SEMAPHORE) Local $LASTERROR = DllCall ("kernel32.dll", "int", "GetLastError") If $LASTERROR[0] = $ERROR_ALREADY_EXISTS Then Exit -1 EndFunc ;==>Singleton and Sleep(10000) Func OnAutoItStart() SingleTon(123123) EndFunc ;==>OnAutoItStart Func SingleTon($SEMAPHORE) Local $ERROR_ALREADY_EXISTS = 183 DllCall ("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $SEMAPHORE) Local $LASTERROR = DllCall ("kernel32.dll", "int", "GetLastError") If $LASTERROR[0] = $ERROR_ALREADY_EXISTS Then Exit -1 EndFunc ;==>Singleton and it does not work either. So for what can I see your script simply does not work.
Matt @ MPCS Posted October 8, 2004 Posted October 8, 2004 Unpleasant as usual Valik. This second answer have a meaning since I was using @scriptfullpath because I created a script that works in its folder and its subfolders, but I wanted to use it at the same time other copies in other folders. Indeed, I have nothing agaist you, but you should think that others people are not always clueless AND stupid AND do not read as you seems to think.Btw, I also tried:Sleep(10000) Func OnAutoItStart() SingleTon('abcabc') EndFunc;==>OnAutoItStart Func SingleTon($SEMAPHORE) Local $ERROR_ALREADY_EXISTS = 183 DllCall ("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $SEMAPHORE) Local $LASTERROR = DllCall ("kernel32.dll", "int", "GetLastError") If $LASTERROR[0] = $ERROR_ALREADY_EXISTS Then Exit -1 EndFunc;==>Singletonand Sleep(10000) Func OnAutoItStart() SingleTon(123123) EndFunc;==>OnAutoItStart Func SingleTon($SEMAPHORE) Local $ERROR_ALREADY_EXISTS = 183 DllCall ("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $SEMAPHORE) Local $LASTERROR = DllCall ("kernel32.dll", "int", "GetLastError") If $LASTERROR[0] = $ERROR_ALREADY_EXISTS Then Exit -1 EndFunc;==>Singletonand it does not work either. So for what can I see your script simply does not work.<{POST_SNAPBACK}>Valik is never cruel... just brutally honest.*** Matt @ MPCS
Valik Posted October 8, 2004 Author Posted October 8, 2004 From what I can tell, my script works perfectly fine. Even using your examples, including attempting to run mixed compiled and uncompiled versions of the same script. Only the first instance runs, any other attempt to run a compile/non-compiled version dies out immediately.However, if your goal is to run multiple copies of the same script from different locations, why the hell do you need to use the singleton pattern at all?As for treating you like you don't know what you're doing, lets review the facts, shall we? I explain how to use this function. You show an example of using the function and it doesn't work. You aren't using the function as per my description of how to use it. You do not explain why you are not using it like I said.If you don't want somebody to get on you about incorrectly using something, then explain to them why you are using it in a different manner than they describe. Otherwise, you get what you got.
Valik Posted October 8, 2004 Author Posted October 8, 2004 Valik is never cruel... just brutally honest.*** Matt @ MPCS<{POST_SNAPBACK}>There's a difference between "never cruel" and "not cruel yet".
Matt @ MPCS Posted October 8, 2004 Posted October 8, 2004 From what I can tell, my script works perfectly fine. Even using your examples, including attempting to run mixed compiled and uncompiled versions of the same script. Only the first instance runs, any other attempt to run a compile/non-compiled version dies out immediately. However, if your goal is to run multiple copies of the same script from different locations, why the hell do you need to use the singleton pattern at all? As for treating you like you don't know what you're doing, lets review the facts, shall we? I explain how to use this function. You show an example of using the function and it doesn't work. You aren't using the function as per my description of how to use it. You do not explain why you are not using it like I said.If you don't want somebody to get on you about incorrectly using something, then explain to them why you are using it in a different manner than they describe. Otherwise, you get what you got. <{POST_SNAPBACK}>Is there a chance that the API call was changed between your versions of Windows? I know ezzetabi said he was running WinXP SP2... Valik is your testing platform the same? Just a thought, I haven't seen it done since Win3.1 -> Win95 but MS has done stranger things. *** Matt @ MPCS
Valik Posted October 8, 2004 Author Posted October 8, 2004 The function is standard in all versions of Windows. I use XP Pro SP2.
Guest s_mack Posted December 7, 2005 Posted December 7, 2005 (edited) Hello! Someone suggested I use this _Singleton UDF but, of course, I dont' want to do so blindly especially since it is beyond the realm of my knowledge. I'm *just* above "newbie" status I just noticed there hasn't been any discussion on this in over a year, and that now the whole CreateSemaphore line in the misc file is commented out (does that mean the guy that didn't know what he was talking about was on to something?). i don't require any explanation I can't understand (which is likely anything you'll write) so all I want to know is if this _Singleton is reliable and safe to use for the purpose of discarding multiple instances of the same AutoIt executable? Or does it have bugs? Will it work on all versions of Windows? Thanks! - Steven ps. to be sure we're on the same page, this is the code for the function in question: ;=============================================================================== ; ; Description: _Singleton ; Parameter(s): $occurenceName ; $flag ; User CallTip: _Singleton($occurenceName [,$flag = 0]) Check if no other occurence is running. (required: <Misc.au3>) ; Return Value(s): if $flag = 1 ; Author(s): Jason Boggs <vampire dot valik at gmail dot com> ; ;=============================================================================== Func _Singleton($occurenceName, $flag=0) Local $ERROR_ALREADY_EXISTS = 183 $occurenceName=StringReplace($occurenceName,"\", ""); to avoid error ; Local $handle = DllCall("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $occurenceName) Local $handle = DllCall("kernel32.dll", "int", "CreateMutex", "int", 0, "long", 1, "str", $occurenceName) Local $lastError = DllCall("kernel32.dll", "int", "GetLastError") If $lastError[0] = $ERROR_ALREADY_EXISTS Then If $flag = 0 Then Exit -1 Else SetError($lastError[0]) Return 0 EndIf EndIf Return $handle[0] EndFunc; _Singleton() Edited December 7, 2005 by s_mack
jpm Posted December 7, 2005 Posted December 7, 2005 Hello! Someone suggested I use this _Singleton UDF but, of course, I dont' want to do so blindly especially since it is beyond the realm of my knowledge. I'm *just* above "newbie" status I just noticed there hasn't been any discussion on this in over a year, and that now the whole CreateSemaphore line in the misc file is commented out (does that mean the guy that didn't know what he was talking about was on to something?). i don't require any explanation I can't understand (which is likely anything you'll write) so all I want to know is if this _Singleton is reliable and safe to use for the purpose of discarding multiple instances of the same AutoIt executable? Or does it have bugs? Will it work on all versions of Windows? Thanks! - Steven ps. to be sure we're on the same page, this is the code for the function in question: ;=============================================================================== ; ; Description: _Singleton ; Parameter(s): $occurenceName ; $flag ; User CallTip: _Singleton($occurenceName [,$flag = 0]) Check if no other occurence is running. (required: <Misc.au3>) ; Return Value(s): if $flag = 1 ; Author(s): Jason Boggs <vampire dot valik at gmail dot com> ; ;=============================================================================== Func _Singleton($occurenceName, $flag=0) Local $ERROR_ALREADY_EXISTS = 183 $occurenceName=StringReplace($occurenceName,"\", ""); to avoid error ; Local $handle = DllCall("kernel32.dll", "int", "CreateSemaphore", "int", 0, "long", 1, "long", 1, "str", $occurenceName) Local $handle = DllCall("kernel32.dll", "int", "CreateMutex", "int", 0, "long", 1, "str", $occurenceName) Local $lastError = DllCall("kernel32.dll", "int", "GetLastError") If $lastError[0] = $ERROR_ALREADY_EXISTS Then If $flag = 0 Then Exit -1 Else SetError($lastError[0]) Return 0 EndIf EndIf Return $handle[0] EndFunc; _Singleton()as you have the code did you look at the doc of the official release for the used functions? I this specific case not so may DLLCall, SetError, StringReplace and Func. I am for sure you could have found out that's this function work any release. For the commented line it was a modification I did to Valik code when I proposed to include it iin the standard "Misc.au3".
Guest s_mack Posted December 7, 2005 Posted December 7, 2005 as you have the code did you look at the doc of the official release for the used functions?I this specific case not so may DLLCall, SetError, StringReplace and Func.I am for sure you could have found out that's this function work any release.For the commented line it was a modification I did to Valik code when I proposed to include it iin the standard "Misc.au3". Can you not see where I said I was a newbie!??! Lol... no, of course I can't tell (whatever it is you just mumbled out) from looking at the code because I have no idea how it works. How would I have found out that the function works for any release of Windows?? Sure, I looked at the help file - it doesn't say that.Anyway (frustrates me to no end when people look down at you for no reason other than to feel geek-superiority) does that mean that yes, it is safe and stable in all releases of Windows? - Steven
piccaso Posted December 7, 2005 Posted December 7, 2005 if i get things right it should work since win95 CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map
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