Terenz Posted October 25, 2016 Posted October 25, 2016 (edited) Hello, _Singleton is a controversy function, for unknow reason not work for everybody. The first version was using semaphore, the actual mutex. There is another alternative, CreateEvent. If _SingletonEx("Global\MyApp", 1) = 0 Then MsgBox(16, "Warning", "An occurrence of test is already running") Exit EndIf MsgBox(64, "OK", "The first occurrence of test is running") Func _SingletonEx($sOccurrenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 Local $hStartEvent = DllCall("kernel32.dll", "handle", "CreateEventW", "struct*", 0, "bool", False, "bool", False, "wstr", $sOccurrenceName) If @error Then Return SetError(@error, @extended, 0) Local $hError = DllCall("kernel32.dll", "dword", "GetLastError") If $hError[0] = $ERROR_ALREADY_EXISTS Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hStartEvent[0]) If @error Then Return SetError(@error, @extended, 0) If BitAND($iFlag, 1) Then Return SetError($hError[0], $hError[0], 0) Else Exit -1 EndIf EndIf Return $hStartEvent[0] EndFunc ;==>_SingletonEx On my system work fine also without the $tSecurityAttributes for the Global\ since the switch between my two user recognize the old instance running, test also on your enviroment. Please be gentle, i'm not so expert in structure and DllCall. If i have loose time and the actual _Singleton() is better then mine isn't a problem for me, I won't be offended P.S. In thoery we need a CloseHandle for CreateEvent when the script has only 1 instance at exit. Since the original _Singleton() don't close the handle for the Mutex in the same situation and leave to do by Autoit at exit, i have do it the same. Another one, with FileMapping If _SingletonMap("Global\MyApp", 1) = 0 Then MsgBox(16, "Warning", "An occurrence of test is already running") Exit EndIf MsgBox(64, "OK", "The first occurrence of test is running") Func _SingletonMap($sOccurrenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 Local $tInt64 = DllStructCreate('int64') Local $tQWord = DllStructCreate('dword;dword', DllStructGetPtr($tInt64)) DllStructSetData($tInt64, 1, 1) Local $iSize_HiDWord = DllStructGetData($tQWord, 2), $iSize_LoDWord = DllStructGetData($tQWord, 1) Local $hStartEvent = DllCall('kernel32.dll', 'handle', 'CreateFileMappingW', 'handle', -1, 'struct*', 0, 'dword', 0x0004, 'dword', $iSize_HiDWord, 'dword', $iSize_LoDWord, 'wstr', $sOccurrenceName) If @error Then Return SetError(@error, @extended, 0) Local $hError = DllCall("kernel32.dll", "dword", "GetLastError") If $hError[0] = $ERROR_ALREADY_EXISTS Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hStartEvent[0]) If @error Then Return SetError(@error, @extended, 0) If BitAND($iFlag, 1) Then Return SetError($hError[0], $hError[0], 0) Else Exit -1 EndIf EndIf Return $hStartEvent[0] EndFunc With CreateWaitableTimer If _SingletonWT("Global\MyApp", 1) = 0 Then MsgBox(16, "Warning", "An occurrence of test is already running") Exit EndIf MsgBox(64, "OK", "The first occurrence of test is running") Func _SingletonWT($sOccurrenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 $hStartEvent = DllCall("kernel32.dll", "long", "CreateWaitableTimer", "long", 0, "long", True, "str", $sOccurrenceName) If @error Then Return SetError(@error, @extended, 0) Local $hError = DllCall("kernel32.dll", "dword", "GetLastError") If $hError[0] = $ERROR_ALREADY_EXISTS Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hStartEvent[0]) If @error Then Return SetError(@error, @extended, 0) If BitAND($iFlag, 1) Then Return SetError($hError[0], $hError[0], 0) Else Exit -1 EndIf EndIf Return $hStartEvent[0] EndFunc ;==>_SingletonEx With Semaphore, like the original Valik function but improved with CloseHandle and error checking. If _SingletonSemaphore("Global\MyApp", 1) = 0 Then MsgBox(16, "Warning", "An occurrence of test is already running") Exit EndIf MsgBox(64, "OK", "The first occurrence of test is running") Func _SingletonSemaphore($sOccurrenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 $hStartEvent = DllCall('kernel32.dll', 'handle', 'CreateSemaphoreW', 'struct*', 0, 'long', 0, 'long', 1, 'wstr', $sOccurrenceName) If @error Then Return SetError(@error, @extended, 0) Local $hError = DllCall("kernel32.dll", "dword", "GetLastError") If $hError[0] = $ERROR_ALREADY_EXISTS Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hStartEvent[0]) If @error Then Return SetError(@error, @extended, 0) If BitAND($iFlag, 1) Then Return SetError($hError[0], $hError[0], 0) Else Exit -1 EndIf EndIf Return $hStartEvent[0] EndFunc ;==>_SingletonEx This was made just for fun from C# code: Global $iListenSingleton If _SingletonTCP(12345, 1) = 0 Then MsgBox(16, "Warning", "An occurrence of test is already running") Exit EndIf MsgBox(64, "OK", "The first occurrence of test is running") OnAutoItExitRegister("_SingletonExit") Func _SingletonTCP($iOccurrence, $iFlag = 0) If Not IsNumber($iOccurrence) Then Return SetError(1, 0, 0) Local Const $WSAEADDRINUSE = 10048 TCPStartup() $iListenSingleton = TCPListen("127.0.0.1", $iOccurrence) If @error = $WSAEADDRINUSE Then If BitAND($iFlag, 1) Then Return 0 Else Exit -1 EndIf EndIf Return 1 EndFunc ;==>_SingletonTCP Func _SingletonExit() TCPCloseSocket($iListenSingleton) TCPShutdown() EndFunc ;==>_SingletonExit All version work globally on multi user enviroment. Edited October 26, 2016 by Terenz KaFu 1 Nothing is so strong as gentleness. Nothing is so gentle as real strength
BrewManNH Posted October 25, 2016 Posted October 25, 2016 Where have you seen anything related to _Singleton not working for some people? There's nothing in the bugtracker about it, so I'm surious how you determined there was an issue? If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! Reveal hidden contents I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator
Terenz Posted October 25, 2016 Author Posted October 25, 2016 (edited) I'll post one. From 2014: Another example made on the first post using FileMapping. Many API has ERROR_ALREADY_EXISTS there is plenty of choice. For example i don't have understood why "Semaphore" was replaced by "Mutex", i don't say one is better then the other but the principe is the same, check if ERROR_ALREADY_EXISTS. EDIT: BrewManNH you took part in that discussion and ask to me? LOL Edited October 25, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
BrewManNH Posted October 25, 2016 Posted October 25, 2016 And as I wrote in the second page of that thread, I have never been able to duplicate the problem that was mentioned. Write a script that demonstrates the issue for you, figure out where in the script it's failing, and report back. Otherwise, we'll have to guess that it's a computer issue and not a function issue. Do a line by line filewrite of all variable, and object contents, and see if you can determine what's happening. Creating another function that does the same thing as _Singleton doesn't help the situation for everyone. If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! Reveal hidden contents I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator
Terenz Posted October 25, 2016 Author Posted October 25, 2016 (edited) It does't do the same thing of _Singleton() only the principle is the same, the API is different. CreateWindowEx, that has nothing to do with _Singleton(), can return ERROR_ALREADY_EXISTS. There is also CreateFile, CreateProcess, CreateDirectory, CreateFileMapping ( see the example ) etc. i'll repeat plenty of API with that error code. Do you think a guy like @KaFu that actually ( or in the past ) have a problem with _Singleton() can't use any of that API above? We are forced to use CreateMutex ( why CreateMutex suppress CreateSemaphore? ) until the rest of our days? Is not better to switch with another API more "compatible" since the principle is the same? I don't have that problem anyway on my machine but in the past on a friend PC yes, i wasn't able to debug i was too n00b Edited October 25, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
Terenz Posted October 26, 2016 Author Posted October 26, 2016 (edited) Added another example with CreateWaitableTimer and Semaphore, i think i have done with this also if there are other kernel object like jobs, namedpipe and so on. Some bat-signal for people can't make _Singleton() work in other threads of the forum: @Morthawt, @iamtheky, @WhiteLion, @martin, @Bridawg, @therks, @jchd You are not force to do nothing or post here, just for let you know. But if _Singleton() UDF not work it today and want to test one of my versions i'm glad and *maybe* i can make a ticket for replace-improve actual version. I have imagined more participants to this thread Edited October 26, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
Terenz Posted October 26, 2016 Author Posted October 26, 2016 On 10/25/2016 at 11:09 AM, Terenz said: P.S. In thoery we need a CloseHandle for CreateEvent when the script has only 1 instance at exit. Since the original _Singleton() don't close the handle for the Mutex in the same situation and leave to do by Autoit at exit, i have do it the same. Expand After this i'll stop to talk by myself. This is what i mean with that quote, added a GUI just for change. expandcollapse popup#include <GUIConstantsEx.au3> Local $aSingleton[2] = [0, "Global\MyApp"] ; declare 1D array for hWnd and OccurranceName Local $iResult = _SingletonRead($aSingleton, 1) If @error Then MsgBox(16, "DEBUG", "An error occurred" & @CRLF & "ERROR: " & @error & @CRLF & "EXTENDED: " & @extended) EndIf If $iResult = 0 Then ; check if already semaphore exist MsgBox(16, "Warning", "An occurrence of test is already running") Exit EndIf _SingletonInit($aSingleton) ; initiate new singleton If @error Then MsgBox(16, "DEBUG", "An error occurred" & @CRLF & "ERROR: " & @error & @CRLF & "EXTENDED: " & @extended) EndIf Local $hGUI = GUICreate("_Singleton", 200, 150, -1, -1) GUICtrlCreateLabel("START ANOTHER INSTANCE", 23, 65) GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE _SingletonRelease($aSingleton) ; release the resource GUIDelete($hGUI) Exit EndSwitch WEnd Func _SingletonRead($aOccurrenceName, $iFlag = 0) Local $hOpenSemaphore = DllCall('kernel32.dll', 'handle', 'OpenSemaphoreW', 'dword', 0x001F0003, 'bool', 0, 'wstr', $aOccurrenceName[1]) If @error Then Return SetError(@error, @extended, -1) If $hOpenSemaphore[0] = 0 Then Return 1 DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hOpenSemaphore[0]) If @error Then Return SetError(@error, @extended, 0) If BitAND($iFlag, 1) Then Return 0 Else Exit -1 EndIf EndFunc ;==>_SingletonRead Func _SingletonInit(ByRef $aOccurrenceName) Local $tSecurityDescriptor = DllStructCreate("byte;byte;word;ptr[4]") Local $aError, $aReturn = DllCall("advapi32.dll", "bool", "InitializeSecurityDescriptor", "struct*", $tSecurityDescriptor, "dword", 1) If @error Then Return SetError(@error, @extended, 0) If Not $aReturn[0] Then $aError = DllCall("kernel32.dll", "dword", "GetLastError") Return SetError(@error, @extended, $aError[0]) EndIf $aReturn = DllCall("advapi32.dll", "bool", "SetSecurityDescriptorDacl", "struct*", $tSecurityDescriptor, "bool", 1, "ptr", 0, "bool", 0) If @error Then Return SetError(@error, @extended, 0) If Not $aReturn[0] Then $aError = DllCall("kernel32.dll", "dword", "GetLastError") Return SetError(@error, @extended, $aError[0]) EndIf Local $tSecurityAttributes = DllStructCreate("dword Length;ptr Descriptor;bool InheritHandle") DllStructSetData($tSecurityAttributes, 1, DllStructGetSize($tSecurityAttributes)) DllStructSetData($tSecurityAttributes, 2, DllStructGetPtr($tSecurityDescriptor)) DllStructSetData($tSecurityAttributes, 3, 0) Local $aResult = DllCall('kernel32.dll', 'handle', 'CreateSemaphoreW', 'struct*', $tSecurityAttributes, 'long', 0, 'long', 1, 'wstr', $aOccurrenceName[1]) If @error Then Return SetError(@error, @extended, 0) $aOccurrenceName[0] = $aResult[0] ; set handle to zero index of the array EndFunc ;==>_SingletonInit Func _SingletonRelease($aOccurrenceName) DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aOccurrenceName[0]) If @error Then Return SetError(@error, @extended, 0) EndFunc ;==>_SingletonRelease if we want to do "good coding" so release all handle before close, do a better error checking, the security descriptor, don't create and check for ERROR_ALREADY_EXISTS but instead read if exist. I have use Semaphore but can be applied to every example posted before. That's all. Nothing is so strong as gentleness. Nothing is so gentle as real strength
iamtheky Posted October 26, 2016 Posted October 26, 2016 I havent messed with singleton in a while, I will try this in the coming week. You've only given it 24 hours and singleton is a pretty niche need, so dont be discouraged. I did have issues year(s) ago with it but settled for a one-liner that enumerated processes and if scriptname existed then exit. It just required that I use unique names. Reveal hidden contents ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__)
Terenz Posted October 26, 2016 Author Posted October 26, 2016 (edited) I know every "alternative" function to _Singleton, a couple made also by MPVs. Since the function is there from 2005, lol 11 years ago, and we still found people in the recent years, like you, with problem with that imho we have two ways: 1) Ask to remove _Singleton() from UDF library 2) Fix it and make it work for everyone, not 99% yes and 1% not ( random numbers ) I'll try, in my little with my limited knowledge, to fix it with alternative APIs ( post #1 ) and an alternative approach ( post #7 ) Test it when you want but if actual _Singleton() work for you now well unfortunately we can't consider it a "valid test" if you know what i mean. Thanks. Edited October 26, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
therks Posted October 26, 2016 Posted October 26, 2016 Thanks for tagging me @Terenz. While I have since rewritten my code to use my own singleton-like process, I will give your code a test on my laptop when I get back on it tonight. @BrewManNH, for what it's worth, if you have a look at the thread I started, I'm getting virtually the same results today with the newest version of AutoIt, so it's still a problem. You say it's not a function issue, but shouldn't a function that's quite possibly integral to the proper operation of a program, and that is included with AutoIt with no warnings about its inconsistency, work properly unless the end user is going out of their way to defeat it? It's not like I was specifically trying to break _Singleton() when I discovered the issue. I had simply created a program on my home PC that incorporated _Singleton(), and it ran perfectly in all my tests. Fast forward a couple years and I get a laptop. I put the program on my laptop and didn't even realize for months that it wasn't working properly, simply because I never accidentally ran it twice. At that point I did a bunch of testing trying to figure out how I was breaking the program, only to discover that it was a flaw in the function itself, and not in my code. I also then realized that I had several different compiled programs that relied on _Singleton() and they would need to be rewritten and recompiled (which was a small hassle since the version changes since the original compile had included several script breaking changes). My AutoIt Stuff | My Github
Terenz Posted October 26, 2016 Author Posted October 26, 2016 You are welcome @therks. Please test all the version so CreateEventW, CreateFileMappingW, CreateWaitableTimer and CreateSemaphoreW. For the last one try both post 1# and #7. I'll really hope one of that will work, if not we'll try to debug in some way. I'm sure ( well "sure" is a big word, better to say "i think" ) is CreateMutex the problem, in some way not compatible with any system/configuration for unknow reason. P.S. Remember the example are with Global\ so also other user in a multi-user enviroment, in theory, can't access to your script doesn't care if they are admin or standard. I'm sure you know how _Singleton() work but i'll write it for future reference: Copy-paste-save the script ( compile or not will work at the same, try in both way ) launch the script, wait for the MsgBox with text "The first occurrence of test is running", DON'T CLOSE the Msgbox, start the script again. A new Msgbox will appear with the text "An occurrence of test is already running" Nothing is so strong as gentleness. Nothing is so gentle as real strength
Danyfirex Posted October 26, 2016 Posted October 26, 2016 @therks Hello. would be great if you can check AutoIt Default singleton (API and Dll call Return values) to be able to check where the issue is coming... Saludos Danysys.com AutoIt... Reveal hidden contents UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
BrewManNH Posted October 26, 2016 Posted October 26, 2016 On 10/26/2016 at 2:10 PM, therks said: You say it's not a function issue, but shouldn't a function that's quite possibly integral to the proper operation of a program, and that is included with AutoIt with no warnings about its inconsistency, work properly unless the end user is going out of their way to defeat it? Expand As far as I am aware of, the function is written properly, and if you're having a problem are you SURE that it's the function and not the PC it's running on? On 10/26/2016 at 2:10 PM, therks said: At that point I did a bunch of testing trying to figure out how I was breaking the program, only to discover that it was a flaw in the function itself, and not in my code Expand If there's a problem with the function let us know what you found out. The only person/people that can help with fixing the original function are the ones that are experiencing an issue with it. If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! Reveal hidden contents I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator
Terenz Posted October 26, 2016 Author Posted October 26, 2016 (edited) After 11 years i don't think we can able to debug, or is a problem of the API of internally to Autoit. At least a couple of attempt have made to debug, Kafu for example with the problem of _Singleton() has the error "The specified module could not be found". So? What do you do with this information now? All of they have problems with their PC but only _Singleton suffers? Come on. Since for us don't change nothing to use a different API ( the function is pratically the same! ) is more simple to change the approach / the API actually used insted to try, i'll repeat after 11 years, to understand why Mutex not work in some scenario. Using semaphore/event/job/whatever, assuming work for therks, is the same and you get EXACTLY the same result of Mutex. Edited October 26, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
iamtheky Posted October 26, 2016 Posted October 26, 2016 there have definitely been issues with singleton. But also why wait or even discuss the merits in this manner? Wrap yours up and call it _singletonEx, and it now exists. If it catches on with a vocal minority bearing valid reproduers, it will get folded in like all the other _*Ex UDFs. Reveal hidden contents ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__)
Terenz Posted October 27, 2016 Author Posted October 27, 2016 (edited) I'll discuss it because i don't what to make the N alternative to _Singleton ( we have 5-6 different version, with PID, hardware id, process name, file lock, autoit title, probably forget a couple, and in this list i don't want to add mine with TCP or other APIs ) but i'd like to make a dot to this story, trash that and replace with one that work for everyone. This is probably the only autoit function, integrated or in the UDF, that have so many "unofficial" way that give the same result of the original one, without adding nothing more that is so essential or different. It has so many alternative for one reason and everybody knows why, _Singleton() in some scenario\situation rare or not don't work. P.S. After some research i have found why CreateMutex suppress CreateSemaphore. Has i have already say the original function was with semaphore. When that function was integrated in the UDF by ticket one of dev arbitrarily, without any public explanation, replace semaphore with mutex and leave the function as it it. The error checking and the security descriptor was added later. Original one was 4 line of 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 P.P.S Mutex is very common for malware/bot. It is used for detect whether an operating system has any security programs installed on it or avoid double infection of the OS. So in theory any security software can monitor Mutex API and maybe block the execution, don't forget how many false-positive we have with Autoit. So this is another reason to avoid the use of Mutex and choose an alternative API. Edited October 27, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
Terenz Posted October 27, 2016 Author Posted October 27, 2016 (edited) On 10/27/2016 at 7:17 AM, Terenz said: P.P.S Mutex is very common for malware/bot. It is used for detect whether an operating system has any security programs installed on it or avoid double infection of the OS. So in theory any security software can monitor Mutex API and maybe block the execution, don't forget how many false-positive we have with Autoit. So this is another reason to avoid the use of Mutex and choose an alternative API. Expand And this the proof! A script compiled ( NO UPX ) with _Singleton() i have simply take the example provide here, nothing else: _Singleton And the result is...drumroll: https://virustotal.com/en/file/5ee651362ae24de352e993d37c0dd3d6643910f5b1b6d0ea49717172bece04b8/analysis/1477566486/ 9 detection. What happened if i compile a couple of the example above, without UPX? https://virustotal.com/en/file/042ea5991d5b413f0aa5edb0a516afef0201004ef38e907621d0a3a303f700bf/analysis/1477567292/ https://virustotal.com/en/file/a7670e55044d0e00b0a47bb1dcc045bcc2485ab1ef395b3a9533931273e3b198/analysis/ https://virustotal.com/en/file/29ccfad5e09135c8160d50d38d558211fc4e9dfc745a08542fb677f425ef516f/analysis/ https://virustotal.com/en/file/689d1359cbe617416279694c7fb9ebf58b715c76c1b2f338717a6d040d5c8d52/analysis/1477568202/ Uhm...i see 6 detection for three and 5 detection for CreateFileMapping. So using CreateMutex *seems* give to us +3/+4 more detection respect to other APIs. I believe it is appropriate to stop defending _Singleton() and think to an alternative, whatever API you like from the first post is better then the actual for all the reason provided in this thread. Edited October 27, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
therks Posted October 27, 2016 Posted October 27, 2016 @Terenz, I have good and bad news. I tested each of those scripts and, except for the TCP and GUI examples, they all failed to perform as expected. In every instance GetLastError returns 126 (ERROR_MOD_NOT_FOUND). On 10/26/2016 at 3:25 PM, BrewManNH said: As far as I am aware of, the function is written properly, and if you're having a problem are you SURE that it's the function and not the PC it's running on? Expand At first I agreed with this (the function being written properly) however, after testing Terenz' scripts and checking the variables, I rediscovered that all my issues stem back to GetLastError returning a value that the function isn't checking for. The function only checks if it returns 183 (ERROR_ALREADY_EXISTS) but in my case it's consistently returning 126 (ERROR_MOD_NOT_FOUND). This is the same issue that @KaFu and I had in the thread I linked to previously. I'm not that familiar with GetLastError, does it often return false positives or unrelated errors? That's the only reason I can think of for the function to ignore any error besides 183. My AutoIt Stuff | My Github
Terenz Posted October 27, 2016 Author Posted October 27, 2016 (edited) That's really shock me @therks an unexpected result! You can't load any kernel object... Try this: $aDLL1 = DllOpen("kernel32.dll") If $aDLL1 = -1 Then MsgBox(16, "ERROR", "Can't load the DLL 1") MsgBox(64, "INFO", "DLL LOADED 1: " & $aDLL1) $aDLL2 = DllOpen(@SystemDir & "\kernel32.dll") If $aDLL2 = -1 Then MsgBox(16, "ERROR", "Can't load the DLL 2") MsgBox(64, "INFO", "DLL LOADED 2: " & $aDLL2) $hStartEvent1 = DllCall($aDLL1, 'handle', 'CreateSemaphoreW', 'struct*', 0, 'long', 0, 'long', 1, 'wstr', 'Test') $hError1 = DllCall($aDLL1, "dword", "GetLastError") MsgBox(64, "INFO", "DLL LOADED: " & $hStartEvent1[0]) MsgBox(64, "INFO", "ERROR: " & $hError1[0]) $hStartEvent2 = DllCall($aDLL1, 'handle', 'CreateSemaphoreW', 'struct*', 0, 'long', 0, 'long', 1, 'wstr', 'Test') Local $hError2 = DllCall($aDLL1, "dword", "GetLastError") MsgBox(64, "INFO", "DLL LOADED: " & $hStartEvent2[0]) MsgBox(64, "INFO", "ERROR: " & $hError2[0]) $hStartEvent3 = DllCall($aDLL2, 'handle', 'CreateSemaphoreW', 'struct*', 0, 'long', 0, 'long', 1, 'wstr', 'Test') Local $hError3 = DllCall($aDLL2, "dword", "GetLastError") MsgBox(64, "INFO", "DLL LOADED: " & $hStartEvent3[0]) MsgBox(64, "INFO", "ERROR: " & $hError3[0]) DllClose($aDLL1) DllClose($aDLL2) Expected value are: 1 2 An handle like 0x000006B0 0 An handle like 0x000006BC ( different then previuos ) 183 An handle like 0x000006BD ( different then previuos ) 183 If you are on 64 Bit OS try also _WinAPI_Wow64EnableWow64FsRedirection EDIT: Check also in the eviroment variable: Local $sEnvVar = EnvGet("PATH") MsgBox(64, "Info", $sEnvVar) C:\Windows and C:\Windows\System32. If you open a CMD windows and simply write and confirm: kernel32.dll The expected result is an MsgBox with text "you can't open it / not associated" or similar with the path of "Kernel32.dll" inside the title. If instead you have a ConsoleWrite like "not recognized as an internal or external command" something not work. P.S. The GUI example at post #7 works? TCP ok but the GUI use semaphore so always a kernel object so is very strange that this work and the others not. The difference is the method applied, instead to check the error for ERROR_ALREADY_EXISTS use OpenSemaphore. On 10/27/2016 at 3:06 PM, therks said: @Terenz, I have good and bad news. I tested each of those scripts and, except for the TCP and GUI examples, they all failed to perform as expected. Expand Edited October 27, 2016 by Terenz Nothing is so strong as gentleness. Nothing is so gentle as real strength
therks Posted October 27, 2016 Posted October 27, 2016 (edited) The script: I got all the results you said I should (I am also confused by this). The path: Looks normal to me. Running kernel32 from command line: I get the error (no program associated). Example in post #7: Yes. Edit: Wow, so I just tested your _SingletonSemaphore function, but using DllOpen first and everything works fine. Also did the same to the Singleton UDF and it ALSO works fine. WTF..? expandcollapse popupFunc _Singleton($sOccurrenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 Local Const $SECURITY_DESCRIPTOR_REVISION = 1 Local $tSecurityAttributes = 0 Local Const $hKernel32 = DllOpen('kernel32.dll') Local $iError, $iExtended, $vReturn Do 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 $tSecurityDescriptor = DllStructCreate("byte;byte;word;ptr[4]") ; Initialize the security descriptor. Local $aRet = DllCall("advapi32.dll", "bool", "InitializeSecurityDescriptor", _ "struct*", $tSecurityDescriptor, "dword", $SECURITY_DESCRIPTOR_REVISION) If @error Then Return SetError(@error, @extended, 0) If $aRet[0] Then ; Add the NULL DACL specifying access to everybody. $aRet = DllCall("advapi32.dll", "bool", "SetSecurityDescriptorDacl", _ "struct*", $tSecurityDescriptor, "bool", 1, "ptr", 0, "bool", 0) If @error Then Return SetError(@error, @extended, 0) If $aRet[0] Then ; Create a SECURITY_ATTRIBUTES structure. $tSecurityAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES) ; Assign the members. DllStructSetData($tSecurityAttributes, 1, DllStructGetSize($tSecurityAttributes)) DllStructSetData($tSecurityAttributes, 2, DllStructGetPtr($tSecurityDescriptor)) DllStructSetData($tSecurityAttributes, 3, 0) EndIf EndIf EndIf Local $aHandle = DllCall($hKernel32, "handle", "CreateMutexW", "struct*", $tSecurityAttributes, "bool", 1, "wstr", $sOccurrenceName) If @error Then $iError = @error $iExtended = @extended $vReturn = 0 ExitLoop EndIf Local $aLastError = DllCall($hKernel32, "dword", "GetLastError") If @error Then $iError = @error $iExtended = @extended $vReturn = 0 ExitLoop EndIf If $aLastError[0] = $ERROR_ALREADY_EXISTS Then If BitAND($iFlag, 1) Then DllCall($hKernel32, "bool", "CloseHandle", "handle", $aHandle[0]) If @error Then $iError = @error $iExtended = @extended $vReturn = 0 ExitLoop EndIf $iError = $aLastError[0] $iExtended = $aLastError[0] $vReturn = 0 ExitLoop Else Exit -1 EndIf EndIf $vReturn = $aHandle[0] Until 1 DllClose($hKernel32) Return SetError($iError, $iExtended, $vReturn) EndFunc ;==>_Singleton I don't know if @KaFu is still around, or was still having the same problem, but I'd be curious to know if this works for him also. Edited October 28, 2016 by therks Added some code KaFu 1 My AutoIt Stuff | My Github
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