-
Posts
10,648 -
Joined
-
Last visited
-
Days Won
13
Reputation Activity
-
jvanegmond got a reaction from faldo in CLASS: HwndWrapper not working?
Ugh.. I see what you're doing wrong now (a fast answer is not always the best). I thought this problem was more complicated.
The window class is: HwndWrapper[sewmain.exe;;e407155a-3d68-4e3d-927c-3d298e0968fa]
It's not: HwndWrapper.
By default it doesn't do a partial match. Try using [REGEXPCLASS:HwndWrapper.*]
-
jvanegmond got a reaction from Abdelrahman in MouseMove didn't Move - (Moved)
Start script with administrator rights?
-
jvanegmond got a reaction from Skeletor in Powerful HTTP Server in Pure AutoIt
This is a full HTTP server written in pure AutoIt. No external libraries are used. The server code is readable and very simple to modify.
Abilities:
A full web server in a single executable. Able to integrate the web pages into your source code and modify its contents with code. ( This is how the first web pages were build ) The ability to send a page with over 1000 images in under 5 seconds. Fully compatible with both Firefox, Internet Explorer 6 through 9, Chrome and Safari. Nearly every line is commented. It helps you understand the code easily, so that you may reuse it and add on new code with ease. GET, POST are both supported and even cookies and sessions are supported This is intended to be a base for any future projects that provide any service over HTTP. Three different servers give you the base code that you need, and nothing you won't need. In the download there is included a short guide on how to choose the right one.
BrettF has done some awesome work and added to capability to retain sessions in this post: >http://www.autoitscript.com/forum/topic/...e-autoit/page__view__findpost_
If you need sessions, you can use his version. This version is added in the above v1.1 download.
Edit: Please find the webserver attached to this post. You guys keep eating my bandwidth and I had to move it again.
webserver_011.zip
-
jvanegmond got a reaction from u0i299pg in HotStrings - String hotkeys
HotStrings are similar to AutoIts HotKey function but they trigger on a string of characters, instead of a key or key combination. This has been built because of popular requested from the community.
Instructions for use: Download the HotString.au3 (from the GitHub link) and put it in the same directory as your script. Then try out the code example below, or use the library in your own application.
Please visit https://github.com/jvanegmond/hotstrings for the download (download zip in bottom right). Or get it directly from master.
Example
#include <HotString.au3> HotStringSet("callme{enter}", examplefunction) While 1 Sleep(10) WEnd Func examplefunction() MsgBox(0,"","You typed callme! :)") EndFunc -
jvanegmond got a reaction from Decibel in Send("{CAPSLOCK off}") does not work?
Opt SendCapslockMode Specifies if AutoIt should store the state of capslock before a Send function and restore it afterwards. 0 = don't store/restore 1 = store and restore (default) -
jvanegmond got a reaction from Gianni in HotStrings - String hotkeys
HotStrings are similar to AutoIts HotKey function but they trigger on a string of characters, instead of a key or key combination. This has been built because of popular requested from the community.
Instructions for use: Download the HotString.au3 (from the GitHub link) and put it in the same directory as your script. Then try out the code example below, or use the library in your own application.
Please visit https://github.com/jvanegmond/hotstrings for the download (download zip in bottom right). Or get it directly from master.
Example
#include <HotString.au3> HotStringSet("callme{enter}", examplefunction) While 1 Sleep(10) WEnd Func examplefunction() MsgBox(0,"","You typed callme! :)") EndFunc -
jvanegmond got a reaction from Hevener in How to make my mouse move in a complete circle continuously
Writing the script again is easier than searching for it. Learn some math(s)!
HotKeySet("{ESC}", "_exit") $centerX = @DesktopWidth / 2 $centerY = @DesktopHeight / 2 $radius = 300 $i = 0 While 1 MouseMove($centerX + ($radius * Cos($i)), $centerY + ($radius * Sin($i)),0) $i += 0.05 Sleep(10) WEnd Func _exit() Exit EndFunc -
jvanegmond got a reaction from taypatte in how to detect if the mouse DOES NOT MOVE ?
$lastMousePos = MouseGetPos() $lastMouseMove = TimerInit() While ( True ) $curMousePos = MouseGetPos() If ( $lastMousePos[0] == $curMousePos[0] And $lastMousePos[1] == $curMousePos[1] ) Then If ( TimerDiff($lastMouseMove) > 10000 ) Then ; 10,000 ms = 10 seconds MsgBox(0, "", "Mouse hasn't moved for 10 seconds.") EndIf Else $lastMousePos = $curMousePos $lastMouseMove = TimerInit() EndIf WEnd
This.
-
jvanegmond got a reaction from Xandy in Array read speed vs variable made from array
Triblade, what an interesting question.
Under the waters, any array is just an address of where to start finding the values in memory. Say you're storing 32-bit integers in an array, this will be stored in a contiguous block of memory. If we were to look at the memory, it would look like:
base address (start) and then 4 bytes integer, 4 bytes integer, 4 bytes integer, and so on.
If the base address of this array is 50, array index 2 is going to be at 50 + (2 x 4) where 4 is the size in bytes of the integer. In statically typed languages, the number of bytes for your value is determined at compile time so this can be 'baked' into the program to avoid any calculations. In AutoIt, a dynamically typed language, there exists something called a variant (based on 2005 source but probably not changed) which can store any type of data: Int, long, double, window handle, and such small data types easily fit in the variant structure. These are stored sequentially for optimization reasons with a minor overhead. Large values such as strings are stored in another location and the variant simply holds the address to this string memory, so this types of data are exceptional and should be considered carefully when thinking about performance.
Multidimensional arrays get turned into flat arrays, where the indexes are multiplied by one another. So $closed[3][4] is just $closed base address + ((3 * 4) * 4). Again taking 4 bytes for each integer. So you can consider $closed[3][4] to be another syntax for $closed[3*4]. This is really not a special case for the underlying language.
The CPU is incredibly fast. He always copies data from RAM to cache in sizes which are called a block. This is mostly 4K of memory at once copied from RAM, which take about 120+ CPU cycles to get into cache. Modern CPU have 3 levels of cache, called L3, L2 and L1. Depending on manufacturer, these caches have different sizes and this is a large contributor into what makes some modern CPU's feel fast and some slow apart from just raw clock speed.
Accessing arrays requires the CPU to multiply the indexes and then get the whole block of memory into cache. Multiplying the dimensions for your array in your script, 0 by 0, is trivial. This takes only 1 or 2 CPU cycles. Actually retrieving the memory from RAM takes 120+ cycles. Once this memory is in cache, it will take less than 20 CPU cycles to retrieve it again. How do we know if memory is still in cache? This depends on a lot of factors, but the main factor here is your operating system.
Your operating system slices the total CPU time up into what are called slices. Each thread on the operating system gets a time slice according to some prioritization mechanism. Familiarity with this might include opening up task manager, seeing the total amount of threads on the system, and changing the priority of a process to High or Realtime. Now do not be alarmed at the 2000+ something threads running on your system. A vast majority of these threads are in sleep mode, and the scheduler simply skips over them.
Our program will be executing within one of these time slices. This means at the start of the time slice, our CPU will get RAM into cache and will as quickly as possible execute our program. The realistic expected time frame of accesses to the same point in memory should be around 120 cycles for the first access and 20 cycles afterwards. As long as we write our code in tight loops, where we are not voluntarily relinquishing CPU time back to the operating system when we are waiting for something, our data should still be in cache.
Realistically, data still being in cache is determined by a cache eviction policy/algorithm and there is really nothing you can do about this other than not submit to thread switches and perhaps write a nice letter to Intel/AMD where you offer a couple of beers and to sacrifice a goat. Each vendor individually has their own cache eviction policy and I believe in x86 or x86-64 these are not standardized and therefore make for a source of competition for these companies.(Citation needed)
Strings and large memory structures are special. In this case, the variant does not hold the data directly but holds a reference to where the data is really stored. This means the CPU must get the array from memory, which points to other blocks of memory which must also be gotten from RAM. This means not only one of those terrible 120+ cycle accesses, but several, just to access one item. There is really no good solution for this with arrays. Other data types which allow elements to be of non-uniform length might be better suited for the application. This is more or less the same for statically typed languages.
THIS COVERS ARRAY ACCESS.
Now keep in mind that code is just another form of data. The code must also be read into CPU cache before it can be executed. If the AutoIt language makes some bad choices regarding caches; this will severely impact performance and may invalidate some or all of the above. For example, code pointing to other code, to other code, which must all be gotten from cache in sequence is going to make a practical program - which follows all the correct performance guidelines - very, very slow. This is why the community prefers to do benchmarks - but there's nothing wrong with a little theory from time to time.
I believe AutoIt to do this mostly pretty OK in practice. The AutoIt source from 2005 seems to confirm this and that's really the best I can do on this part.
Disclaimer: I've had to dumb this down, and only somewhat reflects the intricacies of modern computing.
-
jvanegmond got a reaction from user4157124 in Simple Logging UDF - Log.au3 based on log4j / NLog
This is a logging library for AutoIt. This library allows you to log messages with different log levels. The log levels are $LOG_TRACE, $LOG_DEBUG, $LOG_INFO, $LOG_WARN, $LOG_ERROR, $LOG_FATAL. These levels are described on the Log4j Wikipedia page. Each message is logged to the console (ConsoleWriteError for $LOG_ERROR and $LOG_FATAL and ConsoleWrite for all other levels) and to a file.
You can choose the filename and a directory (see LogFile), but if you don't the log file will be in the same directory as the program and called @ScriptName & ".log". You can also choose to disable logs below a certain log level (see LogLevel). You can also completely customize the format of the log text (see LogFormat).
log.au3
Here's an example on how to use this library:
#include <log.au3> LogTrace("This is an example trace message") LogDebug("This is an example debug message") LogInfo("This is an example info message") LogWarn("This is an example warning message") LogError("This is an example error message") LogFatal("This is an example fatal message") The output looks like this:
[2014-08-13 21:06:50.582 TRACE] This is an example trace message [2014-08-13 21:06:50.582 DEBUG] This is an example debug message [2014-08-13 21:06:50.582 INFO ] This is an example info message [2014-08-13 21:06:50.582 WARN ] This is an example warning message [2014-08-13 21:06:50.591 ERROR] This is an example error message [2014-08-13 21:06:50.591 FATAL] This is an example fatal message Additionally, these functions are available for your convenience:
LogFile($sFileName)
#include <log.au3> LogFile("C:\example.log") LogInfo("This is an example info message") and the output will appear on the C: drive in a file called example.log.
LogLevel($iMinLevel)
#include <log.au3> LogLevel($LOG_INFO) LogTrace("This is an example trace message and it will not appear in the logs") LogInfo("This is an example info message and it will appear in the logs") LogFatal("This is an example fatal message and it will appear in the logs") The LogTrace call will have no effect. Only the LogInfo and LogFatal message will appear in the log.
LogStart()
#include <log.au3> LogStart() LogInfo("This is an example info message") Output:
[2014-08-13 21:14:42.886 INFO ] C:\Users\jvanegmond\Desktop\example.au3 started. [2014-08-13 21:14:42.888 INFO ] This is an example info message LogFormat($fFormatFunc)
#include <log.au3> LogFormat(MyLogFormat) LogTrace("This is an example trace message") LogDebug("This is an example debug message") LogInfo("This is an example info message") LogWarn("This is an example warning message") LogError("This is an example error message") LogFatal("This is an example fatal message") Func MyLogFormat($sLevel, $sMessage) Return @HOUR & ":" & @MIN & ":" & @SEC & " " & StringStripWS($sLevel, 8) & " " & $sMessage EndFunc Shows the output:
11:39:52 TRACE This is an example trace message 11:39:52 DEBUG This is an example debug message 11:39:52 INFO This is an example info message 11:39:52 WARN This is an example warning message 11:39:52 ERROR This is an example error message 11:39:52 FATAL This is an example fatal message
Please let me know what I can remove from this library so that it can fit your use-case better.
Edit: Changes:
v1.2 Support for log format
v1.1 Create directory structure for log file
v1.0 Initial release
-
jvanegmond got a reaction from MilenP in Escape to stop Script
Here's what you do:
If this is the original script:
HotKeySet("{ESC}","Quit") ;Press ESC key to quit While True ;Here start main loop Sleep(20) WEnd Func Quit() Exit EndFunc
Then here it is without stopping on escape:
While True ;Here start main loop Sleep(20) WEnd
Simple.
Edit: Are you using a GUI? If so, then you must call this method to stop it exiting on escape: AutoItSetOption("GUICloseOnESC")
-
jvanegmond got a reaction from Xandy in Time Control
Please link me to where he explained that, because it appears to me that assembly is another language.
While learning AutoIt programming I did not automagically learn assembly, maybe I am missing out?
-
jvanegmond got a reaction from Rott in Ignore mouse/keyboard input
This has not been mentioned before:
Run("taskmgr","", @SW_DISABLE) -
jvanegmond reacted to ripdad in Powerful HTTP Server in Pure AutoIt
I have seen this code section in several scripts over the years, and I just wanted to make clear that you cannot chunk data this way. Once $bData is in the TCPSend buffer, there is nothing else left over to chunk in the above script. TCP internally, will send the data at the pace it's being received on the other end.
In order to do a proper chunk, you would need to split the data into sections before sending it.
Otherwise, this will suffice to send it all at once - at the same time...
Func _HTTP_SendData($hSocket, $bData, $sMimeType, $sReply = "200 OK") Local $sPacket = Binary("HTTP/1.1 " & $sReply & @CRLF & _ "Server: " & $sServerName & @CRLF & _ "Connection: close" & @CRLF & _ "Content-Length: " & BinaryLen($bData) & @CRLF & _; <== Content-Length was misspelled "Content-Type: " & $sMimeType & @CRLF & @CRLF & $bData & @CRLF & @CRLF) TCPSend($hSocket, $sPacket); Send everything at once EndFunc
-
jvanegmond got a reaction from MLO in nping - Console network pinger / network sweeper / network scanner
nping.exe is a console line portable application that scans a network based on a supplied network address from any Windows machine. It is designed for system administrators and other people who are inclined to have need for a simple network scanner. This is finished and complete software.
Output:
Microsoft Windows [Version 6.1.7600] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users\Jos>nping nping.exe scans a network based on a supplied network address. Usage: nping.exe [ipaddress] [local 1-4] [listlocal] Examples: nping.exe 192.168.0.0-1 will ping these addresses: 192.168.0.0 and 192.168.0.1 nping.exe 192.168.20.* will ping everything in the range from 192.168.20.1 to 192.168.20.255 nping listlocal gives you a list of local ipaddresses recognized by the program nping local pings your local network, if your ip addresses is 10.0.5.100 then it will p ing everything in 10.0.5.* C:\Users\Jos>nping 74.125.79.* Pinging 255 addresses in range of 74.125.79.* 74.125.79.4 has a roundtrip of 17 ms 74.125.79.5 has a roundtrip of 18 ms 74.125.79.6 has a roundtrip of 22 ms 74.125.79.18 has a roundtrip of 15 ms 74.125.79.27 has a roundtrip of 15 ms 74.125.79.32 has a roundtrip of 17 ms 74.125.79.47 has a roundtrip of 16 ms 74.125.79.52 has a roundtrip of 15 ms 74.125.79.53 has a roundtrip of 16 ms 74.125.79.54 has a roundtrip of 16 ms 74.125.79.57 has a roundtrip of 19 ms 74.125.79.58 has a roundtrip of 16 ms 74.125.79.77 has a roundtrip of 15 ms 74.125.79.79 has a roundtrip of 17 ms 74.125.79.81 has a roundtrip of 15 ms 74.125.79.82 has a roundtrip of 19 ms 74.125.79.84 has a roundtrip of 13 ms 74.125.79.85 has a roundtrip of 18 ms 74.125.79.86 has a roundtrip of 26 ms 74.125.79.91 has a roundtrip of 22 ms 74.125.79.111 has a roundtrip of 14 ms 74.125.79.114 has a roundtrip of 17 ms 74.125.79.116 has a roundtrip of 19 ms 74.125.79.118 has a roundtrip of 22 ms 74.125.79.142 has a roundtrip of 22 ms 74.125.79.143 has a roundtrip of 23 ms 74.125.79.147 has a roundtrip of 20 ms 74.125.79.149 has a roundtrip of 24 ms 74.125.79.161 has a roundtrip of 21 ms 74.125.79.166 has a roundtrip of 17 ms 74.125.79.184 has a roundtrip of 15 ms 74.125.79.206 has a roundtrip of 24 ms 74.125.79.222 has a roundtrip of 16 ms 74.125.79.223 has a roundtrip of 16 ms 74.125.79.224 has a roundtrip of 16 ms 74.125.79.225 has a roundtrip of 17 ms 74.125.79.226 has a roundtrip of 17 ms 74.125.79.231 has a roundtrip of 21 ms 74.125.79.237 has a roundtrip of 22 ms 74.125.79.230 has a roundtrip of 21 ms 74.125.79.250 has a roundtrip of 18 ms 74.125.79.252 has a roundtrip of 16 ms 74.125.79.254 has a roundtrip of 20 ms Ping statistics for 74.125.79.*: Total hosts pinged: 255 Total hosts UP: 43 [16.86%] Total hosts DOWN: 212 [83.14%] Average roundtrip: 18ms C:\Users\Jos>
Tip ! Use the following command to write the results to a text file, you can then use a batch / AutoIt or VBS script to email you the results:
nping 192.168.20.0-100 > networklog.txtIt will place the results in a file called networklog.txt
Code:
#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_icon=C:\Windows\Installer\{B924C008-D667-3B26-84C6-BD70285F9BFC}\Icon_app.ico #AutoIt3Wrapper_outfile=nping.exe #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_Change2CUI=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Constants.au3> #include <Array.au3> Global Const $MAX_PROCESS = 25 ; A maximum number of processes Global Const $MAX_HOSTS = 16777216 ; A maximum number of hosts to ping due to AutoIt's array limit size, and yes, I can work around it but no, I won't Local $networkRange = "" Local $showLocal = False Local $numOfLocalIp = 1 If @Compiled Then If $CmdLine[0] > 0 Then For $n = 1 to UBound($CmdLine)-1 Switch $CmdLine[$n] Case "/?", "?", "/help", "/info" _showHelp() Exit 0 case "listlocal", "locallist" ConsoleWrite("Local IP addresses known to this machine: " & @CRLF) ConsoleWrite("1: " & @IPAddress1 & @CRLF) ConsoleWrite("2: " & @IPAddress2 & @CRLF) ConsoleWrite("3: " & @IPAddress3 & @CRLF) ConsoleWrite("4: " & @IPAddress4 & @CRLF) ConsoleWrite(@CRLF) ConsoleWrite("Use: nping local # to ping all devices on these networks") Exit 0 case "local" $showLocal = True $n +=1 If $n < UBound($CmdLine) Then If $CmdLine[$n] = Number($CmdLine[$n]) Then $numOfLocalIp = Number($CmdLine[$n]) If $numOfLocalIp < 1 Or $numOfLocalIp > 4 Then ConsoleWrite("Local IP address index number must be between 1 and 4" & @CRLF) Exit 0 EndIf EndIf EndIf Case Else $networkRange = $CmdLine[1] EndSwitch Next Else _showHelp() Exit 0 EndIf EndIf If $showLocal Then $localIp = Execute("@IpAddress" & $numOfLocalIp) $ipParts = StringSplit($localIp, ".") $networkRange = $ipParts[1] & "." & $ipParts[2] & "." & $ipParts[3] & ".*" EndIf Local $tStart = TimerInit() $aArray = _GetIpAddressList($networkRange) If @error = 1 Then ConsoleWrite("There are no addresses to be scanned in this range. Check the syntax of your network range." & @CRLF & @CRLF) _showHelp() Exit 1 EndIf If @error = 2 Then ConsoleWrite("Maximum number of hosts to ping is " & $MAX_HOSTS & ", but you tried to ping " & @extended & " hosts" & @CRLF & @CRLF) _showHelp() Exit 1 EndIf Local $iTotal = UBound($aArray) If $iTotal = 1 Then ConsoleWrite("Pinging " & $iTotal & " address in range of " & $networkRange & @CRLF) Else ConsoleWrite("Pinging " & $iTotal & " addresses in range of " & $networkRange & @CRLF) EndIf ConsoleWrite(@CRLF) Local $aProcess[$MAX_PROCESS] ; An array to keep a reference to spawned processes, in the next loop we fill it with value 0 for reference For $i = 0 To UBound($aProcess) - 1 $aProcess[$i] = 0 Next Local $i = 0 ; which IP are we currently trying to ping ( based on array ) Local $iFinished = 0 ; how many processes have finished pinging Local $iUp = 0 ; Total hosts that are UP Local $iDown = 0 ; Total hosts that are DOWN Local $iTotalRoundTrip = 0 ; Total roundtrip (all the +ms added together) While 1 ; We check all the currently running processes For $n = 0 To UBound($aProcess) - 1 ; Check if we need a spot, and there is an existing spot here If ($i <> UBound($aArray) And $aProcess[$n] == 0) Then $aProcess[$n] = _MSPing($aArray[$i]) ; Spawn a new process in the available spot $i += 1 ; Increment $i so we can do the next process the next time around Else ; Check if this process has been spawned and the process is ready If ($aProcess[$n] <> 0 And _MSPingIsReady($aProcess[$n])) Then ; Get results from the command $sHostname = _MSPingGetHostname($aProcess[$n]) $sResult = _MSPingGetResult($aProcess[$n]) If ($sResult <> -1) Then ; Check if the host is up ConsoleWrite($sHostname & " has a roundtrip of " & $sResult & " ms" & @CRLF) $iUp += 1 $iTotalRoundTrip += $sResult Else $iDown += 1 EndIf ; Free up an empty space for the next address to Ping $aProcess[$n] = 0 ; Increment the total of processes that have finished $iFinished += 1 ; If the total number of finished processes If ($iFinished == UBound($aArray)) Then ExitLoop 2 ; Return EndIf EndIf Next Sleep(50) ; Give existing ping commands some time to process the request WEnd If $iUp = 0 Then ConsoleWrite("No devices replied to the ping in this range" & @CRLF) Exit 0 EndIf Local $percentageUp = Round($iUp / $iTotal * 100, 2) Local $percentageDown = 100-$percentageUp Local $tTotal = TimerDiff($tStart) Local $averageRoundTrip = Round($iTotalRoundTrip / $iUp) Local $sUpPad = "" Local $sDownPad = "" For $i = 0 To 6 - StringLen(String($iUp)) $sUpPad &= " " Next For $i = 0 To 6 - StringLen(String($iDown)) $sDownPad &= " " Next ConsoleWrite(@CRLF) ConsoleWrite("Ping statistics for " & $networkRange & ":" & @CRLF) ConsoleWrite(@TAB & "Total hosts pinged: " & $iTotal & @CRLF) ConsoleWrite(@TAB & "Total hosts UP: " & $iUp & $sUpPad & "[" & $percentageUp & "%]" & @CRLF) ConsoleWrite(@TAB & "Total hosts DOWN: " & $iDown & $sDownPad & "[" & $percentageDown & "%]" & @CRLF) ConsoleWrite(@TAB & "Average roundtrip: " & $averageRoundTrip & "ms" & @CRLF) Func _showHelp() ConsoleWrite("nping.exe scans a network based on a supplied network address." & @CRLF & @CRLF & _ "Usage: nping.exe [ipaddress] [local 1-4] [listlocal]" & @CRLF & @CRLF & _ "Examples: " & @CRLF & " nping.exe 192.168.0.0-1" & @CRLF & " will ping these addresses: 192.168.0.0 and 192.168.0.1" & @CRLF & _ " nping.exe 192.168.20.*" & @CRLF & " will ping everything in the range from 192.168.20.1 to 192.168.20.255" & @CRLF & _ " nping listlocal" & @CRLF & " gives you a list of local ipaddresses recognized by the program" & @CRLF & _ " nping local" & @CRLF & " pings your local network, if your ip addresses is 10.0.5.100 then it will ping everything in 10.0.5.*" & @CRLF) EndFunc Func _GetIpAddressList($ipFormat) If $ipFormat = "" Then Return SetError(1) EndIf $ipFormat = StringReplace($ipFormat, "*", "1-255") $ipSplit = StringSplit($ipFormat, ".") If $ipSplit[0] <> 4 Then TCPStartup() Local $ret[1] = [TCPNameToIP($ipFormat)] If @error Then Return SetError(1) Return $ret EndIf For $i = 1 To 4 If Not StringRegExp($ipSplit[$i], "[0-9\-]*") Then TCPStartup() Local $ret[1] = [TCPNameToIP($ipFormat)] If @error Then Return SetError(1) Return $ret EndIf Next Local $ipRange[4][2], $totalPermu = 1 For $i = 0 To 3 If StringInStr($ipSplit[$i + 1], "-") Then $m = StringSplit($ipSplit[$i + 1], "-") $ipRange[$i][0] = $m[1] $ipRange[$i][1] = $m[2] Else $n = Number($ipSplit[$i + 1]) $ipRange[$i][0] = $n $ipRange[$i][1] = $n EndIf $totalPermu *= $ipRange[$i][1] - $ipRange[$i][0] + 1 Next If $totalPermu > $MAX_HOSTS Then Return SetError(2, String($totalPermu)) EndIf Local $result[$totalPermu], $i = 0 For $a = $ipRange[0][0] To $ipRange[0][1] For $b = $ipRange[1][0] To $ipRange[1][1] For $c = $ipRange[2][0] To $ipRange[2][1] For $d = $ipRange[3][0] To $ipRange[3][1] $result[$i] = $a & "." & $b & "." & $c & "." & $d $i += 1 Next Next Next Next Return $result EndFunc ;==>_GetIpAddressList Func _Exit() Exit EndFunc ;==>_Exit Func _MSPing($sHostname, $timeout = 50) Local $return_struc[4] ; [0] = Result (in ms) ; [1] = The hostname originally used ; [2] = Process handle (for internal use only) ; [3] = Buffer (for internal use only) $return_struc[1] = $sHostname $return_struc[2] = Run("ping " & $sHostname & " -n 1 -w " & $timeout, "", @SW_HIDE, $STDOUT_CHILD) Return $return_struc EndFunc ;==>_MSPing Func _MSPingIsReady(ByRef $return_struc) Return ___MSPingReadOutput($return_struc) EndFunc ;==>_MSPingIsReady Func _MSPingGetResult($return_struc) Return $return_struc[0] EndFunc ;==>_MSPingGetResult Func _MSPingGetHostname($return_struc) Return $return_struc[1] EndFunc ;==>_MSPingGetHostname ; Internal use only Func ___MSPingReadOutput(ByRef $return_struc) $data = StdoutRead($return_struc[2]) If (@error) Then ___MSPingParseResult($return_struc) Return 1 Else $return_struc[3] &= $data Return 0 EndIf EndFunc ;==>___MSPingReadOutput ; Internal use only Func ___MSPingParseResult(ByRef $return_struc) $result = StringRegExp($return_struc[3], "([0-9]*)ms", 3) If @error Then $return_struc[0] = -1 Else $return_struc[0] = $result[0] EndIf EndFunc ;==>___MSPingParseResult
Old version downloads: 180
Download:
nping.exe
-
jvanegmond got a reaction from Stevoisiak in Does Autoit Support ControlClick() on a Java Applet Control Currently?
Yes, you're probably right when you thought this was a limitation of Java applet.
A lot of work has been done with Java already. Maybe you will find it of use: http://www.autoitscript.com/forum/index.php?showtopic=87956
-
jvanegmond got a reaction from Triblade in Array read speed vs variable made from array
Your gist understanding is correct. Except when the array is too large to fit, for example it spans 1 contiguous block of 100MB, this array will just be read into the CPU cache at page-size blocks at a time based on the subscripts you are accessing. This is why sequentially accessing an array is faster than randomly accessing it. The data for the next element will already be in cache.
The test which spudw2k did unfortunately has some problems which make interpreting any meaningful result from it difficult. The array is reinitialized and then accessed immediately after, which can leave the array in the cache. But this depends on CPU make & model. Random numbers are generated in a non-deterministic way, which can affect the outcome of each new test. 10 samples taken is not nearly enough to eliminate random noise, from other programs and the operating system. Probably TimerInit/TimerDiff should be replaced for all such performance measurement scenarios with a straight up call to a QueryPerformanceCounter function, but then DllCall is kinda slow too so it's a lesser of evils decision. There are more problems, none are easy to really properly compensate for.
AutoIt is in this sense not designed with such small performance thoughts in mind. It's better to focus on things we know which will have an affect on performance. Having the data already in cache is referred to as locality of reference and can help in a big way in your initial example. It shouldn't really matter if you copied it into a temporary variable or are accessing it directly, it matters that its in cache or no.
-
jvanegmond got a reaction from Triblade in Array read speed vs variable made from array
Triblade, what an interesting question.
Under the waters, any array is just an address of where to start finding the values in memory. Say you're storing 32-bit integers in an array, this will be stored in a contiguous block of memory. If we were to look at the memory, it would look like:
base address (start) and then 4 bytes integer, 4 bytes integer, 4 bytes integer, and so on.
If the base address of this array is 50, array index 2 is going to be at 50 + (2 x 4) where 4 is the size in bytes of the integer. In statically typed languages, the number of bytes for your value is determined at compile time so this can be 'baked' into the program to avoid any calculations. In AutoIt, a dynamically typed language, there exists something called a variant (based on 2005 source but probably not changed) which can store any type of data: Int, long, double, window handle, and such small data types easily fit in the variant structure. These are stored sequentially for optimization reasons with a minor overhead. Large values such as strings are stored in another location and the variant simply holds the address to this string memory, so this types of data are exceptional and should be considered carefully when thinking about performance.
Multidimensional arrays get turned into flat arrays, where the indexes are multiplied by one another. So $closed[3][4] is just $closed base address + ((3 * 4) * 4). Again taking 4 bytes for each integer. So you can consider $closed[3][4] to be another syntax for $closed[3*4]. This is really not a special case for the underlying language.
The CPU is incredibly fast. He always copies data from RAM to cache in sizes which are called a block. This is mostly 4K of memory at once copied from RAM, which take about 120+ CPU cycles to get into cache. Modern CPU have 3 levels of cache, called L3, L2 and L1. Depending on manufacturer, these caches have different sizes and this is a large contributor into what makes some modern CPU's feel fast and some slow apart from just raw clock speed.
Accessing arrays requires the CPU to multiply the indexes and then get the whole block of memory into cache. Multiplying the dimensions for your array in your script, 0 by 0, is trivial. This takes only 1 or 2 CPU cycles. Actually retrieving the memory from RAM takes 120+ cycles. Once this memory is in cache, it will take less than 20 CPU cycles to retrieve it again. How do we know if memory is still in cache? This depends on a lot of factors, but the main factor here is your operating system.
Your operating system slices the total CPU time up into what are called slices. Each thread on the operating system gets a time slice according to some prioritization mechanism. Familiarity with this might include opening up task manager, seeing the total amount of threads on the system, and changing the priority of a process to High or Realtime. Now do not be alarmed at the 2000+ something threads running on your system. A vast majority of these threads are in sleep mode, and the scheduler simply skips over them.
Our program will be executing within one of these time slices. This means at the start of the time slice, our CPU will get RAM into cache and will as quickly as possible execute our program. The realistic expected time frame of accesses to the same point in memory should be around 120 cycles for the first access and 20 cycles afterwards. As long as we write our code in tight loops, where we are not voluntarily relinquishing CPU time back to the operating system when we are waiting for something, our data should still be in cache.
Realistically, data still being in cache is determined by a cache eviction policy/algorithm and there is really nothing you can do about this other than not submit to thread switches and perhaps write a nice letter to Intel/AMD where you offer a couple of beers and to sacrifice a goat. Each vendor individually has their own cache eviction policy and I believe in x86 or x86-64 these are not standardized and therefore make for a source of competition for these companies.(Citation needed)
Strings and large memory structures are special. In this case, the variant does not hold the data directly but holds a reference to where the data is really stored. This means the CPU must get the array from memory, which points to other blocks of memory which must also be gotten from RAM. This means not only one of those terrible 120+ cycle accesses, but several, just to access one item. There is really no good solution for this with arrays. Other data types which allow elements to be of non-uniform length might be better suited for the application. This is more or less the same for statically typed languages.
THIS COVERS ARRAY ACCESS.
Now keep in mind that code is just another form of data. The code must also be read into CPU cache before it can be executed. If the AutoIt language makes some bad choices regarding caches; this will severely impact performance and may invalidate some or all of the above. For example, code pointing to other code, to other code, which must all be gotten from cache in sequence is going to make a practical program - which follows all the correct performance guidelines - very, very slow. This is why the community prefers to do benchmarks - but there's nothing wrong with a little theory from time to time.
I believe AutoIt to do this mostly pretty OK in practice. The AutoIt source from 2005 seems to confirm this and that's really the best I can do on this part.
Disclaimer: I've had to dumb this down, and only somewhat reflects the intricacies of modern computing.
-
jvanegmond reacted to Danyfirex in DllCall & datatypes
Yes I have but not sure if it's magical. I destroy everything I touch (This is my gift, My curse) lol
It it not so hard. the unicode version you return a Pointer to string (wString Ptr Export) for that you can use wstr as return in the dllcall.
The other one you return a string only for that you get a pointer to a pointer that points to a string lol. that's how I see it. maybe if you use something like String Ptr Export it works. I'm not sure because I dont know freebasic. But it should be something like that I think.
Saludos
-
jvanegmond reacted to Triblade in Array read speed vs variable made from array
Hi all,
I was pondering over a question with regards to the speeds of reading something and did not see this kind of question in a forum search.
The question: What is (technically) faster? Multiple reads from the same 3d array cell, or only once make a 'temp' variable from that cell and read the value from this? I don't know if either has any real impact at all anyway, but just wanted to ask anyway. :-)
There may be a difference if the value holds an integer or a string (or something else) but in my case, is a simple integer.
To hopefully clarify with a small bit of code:
$process = $start - 15 If $xy[$process][3] <> "x" Then If _ArraySearch($open, $process, 1, $open[0][0], 0, 0, 1, 1) <> -1 Then UpdateOpen($xy[$process][5], $closed[0][0]) ElseIf $start > 0 And _ArraySearch($closed, $process, 1, $closed[0][0], 0, 0, 1, 0) = -1 Then Add_open($start, $closed[0][0], $counter, $process) EndIf EndIf You can read from this, that the array $closed[0][0] is being read 3 times. And this goes on further in the code I did not show.
My question boils down to this, should I make a 'temp' variable to hold that $closed[0][0] value until the function is done?
It may not have a real impact on my small script, but I really am interested in the answer at least.
Regards,
Tri.
-
jvanegmond got a reaction from MaxTrax in How do I pin a program to Start Menu
This works in Windows 7:
$objShell = ObjCreate("Shell.Application") $objFolder = $objShell.Namespace("C:\Windows\System32") $objFolderItem = $objFolder.ParseName("calc.exe") For $val in $objFolderItem.Verbs() If StringInStr($val(), "Pin to") Then $val.DoIt() Next -
jvanegmond got a reaction from Tankbuster in Simple Logging UDF - Log.au3 based on log4j / NLog
This is a logging library for AutoIt. This library allows you to log messages with different log levels. The log levels are $LOG_TRACE, $LOG_DEBUG, $LOG_INFO, $LOG_WARN, $LOG_ERROR, $LOG_FATAL. These levels are described on the Log4j Wikipedia page. Each message is logged to the console (ConsoleWriteError for $LOG_ERROR and $LOG_FATAL and ConsoleWrite for all other levels) and to a file.
You can choose the filename and a directory (see LogFile), but if you don't the log file will be in the same directory as the program and called @ScriptName & ".log". You can also choose to disable logs below a certain log level (see LogLevel). You can also completely customize the format of the log text (see LogFormat).
log.au3
Here's an example on how to use this library:
#include <log.au3> LogTrace("This is an example trace message") LogDebug("This is an example debug message") LogInfo("This is an example info message") LogWarn("This is an example warning message") LogError("This is an example error message") LogFatal("This is an example fatal message") The output looks like this:
[2014-08-13 21:06:50.582 TRACE] This is an example trace message [2014-08-13 21:06:50.582 DEBUG] This is an example debug message [2014-08-13 21:06:50.582 INFO ] This is an example info message [2014-08-13 21:06:50.582 WARN ] This is an example warning message [2014-08-13 21:06:50.591 ERROR] This is an example error message [2014-08-13 21:06:50.591 FATAL] This is an example fatal message Additionally, these functions are available for your convenience:
LogFile($sFileName)
#include <log.au3> LogFile("C:\example.log") LogInfo("This is an example info message") and the output will appear on the C: drive in a file called example.log.
LogLevel($iMinLevel)
#include <log.au3> LogLevel($LOG_INFO) LogTrace("This is an example trace message and it will not appear in the logs") LogInfo("This is an example info message and it will appear in the logs") LogFatal("This is an example fatal message and it will appear in the logs") The LogTrace call will have no effect. Only the LogInfo and LogFatal message will appear in the log.
LogStart()
#include <log.au3> LogStart() LogInfo("This is an example info message") Output:
[2014-08-13 21:14:42.886 INFO ] C:\Users\jvanegmond\Desktop\example.au3 started. [2014-08-13 21:14:42.888 INFO ] This is an example info message LogFormat($fFormatFunc)
#include <log.au3> LogFormat(MyLogFormat) LogTrace("This is an example trace message") LogDebug("This is an example debug message") LogInfo("This is an example info message") LogWarn("This is an example warning message") LogError("This is an example error message") LogFatal("This is an example fatal message") Func MyLogFormat($sLevel, $sMessage) Return @HOUR & ":" & @MIN & ":" & @SEC & " " & StringStripWS($sLevel, 8) & " " & $sMessage EndFunc Shows the output:
11:39:52 TRACE This is an example trace message 11:39:52 DEBUG This is an example debug message 11:39:52 INFO This is an example info message 11:39:52 WARN This is an example warning message 11:39:52 ERROR This is an example error message 11:39:52 FATAL This is an example fatal message
Please let me know what I can remove from this library so that it can fit your use-case better.
Edit: Changes:
v1.2 Support for log format
v1.1 Create directory structure for log file
v1.0 Initial release
-
jvanegmond got a reaction from mLipok in AutoIt plugin architecture
After several months pondering how to make the best possible plugin architecture, I have come up with an answer. The code is still in an infancy stage and will require work before it can be applied in "real" projects (PM me if you do want to use this and I'll tag along).
What I've made allows you to load an Au3 script file at runtime and call methods in it. This script doesn't have to implement or change anything. Combine this with other functionality such as what Eval offers and (shameless self promotion ftw) and this has many different possibilities.
There often seems to be some differences in what people expect a plugin architecture should support, but here is what I support:
Sometimes the services interface is not included because it's not needed (say other people). That is what I call a one-way plugin architecture, only the main script can call plugin functions. The architecture in the picture is what I call a two-way plugin architecture and that's what I will be demonstrating in this thread.
Firstly, I have created a one way plugin architecture. With the provided libraries, one can do this:
plugins\hello world.au3:
Func HelloWorld($str) MsgBox(0x40, @ScriptName, $str) EndFunc
plugin loader.au3:
#include "lib\reflection.au3" ; Demonstrating simple plugin loading, one-way ; This can be used when the main script knows which functions are in the plugin and how to use them ; and the plugin does not need to use any functions in the main script (more rare than you think) $script = _RDoFile("plugins\hello world.au3") $script.HelloWorld("Something different this time") $script.Quit()
The _R prefix stands for "_Reflection", because that's what I hope to do eventually fully support with this library. What happens in this example is that the reflection library: Reads the script from the .au3 file, modifies the script so that it can export its function, stores the au3 file as temp.au3, runs it.
For curious minds, the temp.au3 file that is generated looks as following. This is a technique that I call "COM server injection". (And here you can see why I said the project is in its infancy)
#NoTrayIcon ;tehee #include "lib\AutoItObject.au3" Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc") Func _ErrFunc() Return EndFunc _AutoItObject_StartUp() Global $oObject = _SomeObject() Global $hObj = _AutoItObject_RegisterObject($oObject, "Manadar.AutoIt.Plugin") While 1 Sleep(100) WEnd _QuitObject(0) Func _SomeObject() Local $oClassObject = _AutoItObject_Class() $oClassObject.AddMethod("HelloWorld", "HelloWorld") $oClassObject.AddMethod("Quit", "_QuitObject") Return $oClassObject.Object EndFunc Func _QuitObject($oSelf) _AutoItObject_UnregisterObject($hObj) $oObject = 0 Exit EndFunc ; ============= ACTUAL SCRIPT ============= Func HelloWorld($o___________________o, $str) MsgBox(0x40, @ScriptName, $str) EndFunc
The reflection library _RDoFile function uses a method to extract all the functions from the original script, and generates the correct $oClassObject.AddMethod calls when generating the COM object.
The while-loop that is added before the script is optional. It can be disabled with another parameter in _RDoFile and eventually there will be various ways to initialize scripts this way, either partly or completely. This parameter is necessary for two-way plugins, but we'll see that later on.
This shows how simply it is to load an Au3 file and do a bit of "reflection" magic on the code. It greatly increases the versatility and capabilities of AutoIt scripts. The function in its current state can not load Au3 files when the plugin loader script is compiled but that is almost trivial to add.
Now we take a look at two-way plugins, here is the plugin loader script:
; Demonstrating plugin loading, two-way ; Both the plugin and the main script provide an interface ; This is the most common way to deal with plugins ; You simply load the plugins and the plugin defines the additional behavior, ; by adding items to your menus and handling the functionality for them etc. $o = _RImplementInterface("pluginterface.au3", "Manadar.AutoIt.Main") $called = False $script2 = _RDoFile("plugins\hello forums.au3", True) While Not $called Sleep(100) WEnd Func Print($obj, $s) $called = True MsgBox(0x30, "", $s) EndFunc
We see in this example that the plugin loader script wants to expose a function called 'Print', but this could be anything and any number of functions. The plugin is written as follows (most ideal case, and actually works):
plugins\hello forums.au3
#include "pluginterface.au3" Print("Hello AutoIt forums!")
Via the one-way plugin architecture method we can load the plugin, we read the contents, apply COM injection magic, run the script, done. But the same method does not work the other way around because our main script is already running (and COM injection requires restart). What we can do, is let the main script create a COM server which does not require a restart. We do this via the call to _RImplementInterface, this function gets the functions from the pluginterface.au3 file and creates a COM server which exposes these methods to the outside. The pluginterface.au3 file functions connect to the plugin loader script and forward any calls from the plugin there.
The pluginterface.au3 file looks like this and it is possible to entirely automatically generate this file (just when you were thinking: I need to write dumb code for this to work? Lame.):
#include "lib\reflection.au3" $main = _RAttach("Manadar.AutoIt.Main") ; just a call to _AutoItObject_ObjCreate() with cbi: Func Print($s) $main.Print($s) EndFunc
With this approach, we have built a fully two-way interface. The code "needs work" and I put this in various comments through the attached files, but the needs work comments are not complete.
Some ideas for the future:
- COM server injection also exposes global variables like: $script.g_sVar
- Automatic generation of the services interface
- Very complete reflection library, with the library itself also object oriented ($script.GetMethods()[0].Call() capability)
- Support of these features (or similar) in native AutoIt: #1931
Attached I have the examples used in this thread, the reflection library and a version of AutoItObject that supports this (v1.2.4.0 I believe). The examples should work "out of the box" with AutoIt v3.3.6.1 (latest stable atm).
Edit: Forgot to attach file. (Really, Manadar, Really?)
Reflection Au3.zip
-
jvanegmond reacted to minxomat in Using AutoIt in Visual Studio Code
Just a quick one, how you can add AutoIt support in Visual Studio Code.
Download Visual Studio Code Download https://github.com/backr/Visual-Studio-Code-AutoIt Put the "autoit" folder in UserName\.vscode\extensions\ Restart Visual Studio Code Now AutoIt is configured automatically for all available Visual Studio Themes:
-
jvanegmond got a reaction from JohnOne in How computers work
Maybe nitpicking but, INC is not atomic in x86 and you missed bad branch predictions as a leading cause of performance woes, which is arguably the most important next to caching behavior.
@JohnOne you may enjoy http://www.nand2tetris.org/ . I can highly recommend it. Skip the stuff you already know and get programming. You can even do it in AutoIt if you are uncomfortable doing the instructions as suggested.