KB_5K0070: STAT5000 – Programming with the ISE Restful API via AutoIT. Description: This KB article summarizes the STAT5000 application and in the process will hopefully give you pointers on how to modify the application for your own purposes. STAT5000 was designed and coded in one day as an exercise to see how quickly a useful application could be turned around using the Restful interface into the ISE. The design goal of the program was pretty simple. Basically, just jam as much performance and status related information into a single screen AND do this for multiple ISEs so that we could monitor host performance across multiple ISEs from the ISE perspective. It was a very, very, long day (the author had only used AUTOIT for two other programs previously). Why use AutoIt? In late 2009, a quick ‘google’ search of the internet for ‘best automated windows scripting language’ indicated that one method that stood out was a tool called autoit. This tool has been around in the industry for 10+ years now and has quite a following, is relatively simple to use, and is VERY feature rich. This, along with the desire to use a language that was ‘free’ but also easy to pick up for both programmers and non-programmers AND that was capable of creating a final executable that had no installation, dll, or registry dependencies all factored into the decision to use it. Interesting sidebar for those MAG Classic customers out there. Almost 10 years ago AutoIt was used by Xiotech Tech Marketing to create a program that ran as a service on customers servers. The application just sat there and monitored the servers volume freespace and when freespace got too low the application would use the RMC easyscripting/autoscripting language (which this author also designed) to tell the MAGNITUDE storage array to expand its VDisk. VERY early precursor to our existing XIP functionality. THE PROGRAM: STAT5000 was designed from the screen outwards (i.e. literal napkin design). The final screen looked like the following. Red-Green rules apply (better to be handy than handsome): The screen is organized as follows: 1) The upper left is the ISE selector/info/button region. This is where you can: a. type in a new IP address (in the box below the list of IP addresses) and then press Add (or just hit enter). b. delete (remove) and ISE from the list by selecting the IP address and pressing delete (button or key). c. Change the sampling interval by clicking the Sample= button (it will cycle through 5 or so different selections.) Rates aren’t necessarily exact when you used the fastest sampling due to variances in TCP traffic but it is pretty fast. d. Start and Stop captures. Use the Start Captures button…it will change to Stop Captures once captures are started up. Capture interval is sampling interval AND all ISE performance info will be captured to a file that contains the IP address of the ISE with a csv extension. The format can then be fed straight into excel. Column headers are named such that a left to right sort will pull all qdepths together for example (lazy method of quick plotting in excel). e. Age captures…allows you to start a new capture but first age out the existing one…keeps 8 levels deep. f. And in the legend area you can see what all the colors/symbols/etc are for on the rest of the screen. 2) The other 8 regions are each a separate ISE as shown above. Each of these regions shows: a. The ise/mrc/battery/powersupply/datapac status and fw versions/etc where appropriate b. The number of disks (i.e. each show as a disk symbol) within each datapac PLUS the status and activity in each disk. The status is shown by the color of the top of the disk (green is ok, yellow is reduced capacity, and red is failed). The performance is reflected in the color of the disk ‘body’ itself with colors mixed via an algorithm that takes into consideration IOPS, KBPS, QD, and LATENCY. Lighter and brighter the busier they are. Also, under each disk are up to three horizontal lines, the length of which indicates the relative qdepth+latency for the top line, the iops for the middle line, and the kbps for the bottom line. Finally, if the mouse is dragged over any disk, a tooltip will appear showing you much more detailed info about that disk as shown in the full screenshot above (mouse cursor symbol is missing from capture). Left clicking while this screen is up will save the information to a text file and then pop that file up via notepad (useful if you want to remember the info and you have refresh set too fast…the tooltip will continue to update dynamically as you hold the mouse over a disk.) c. The region under the disk symbols is a recent addition (i.e. not in the first day of coding). It can be an eyechart but it shows the performance of each individual volume (there can be up to 240 of them) or, if selected by the user, this region can just show the performance of each host hba. These are tiny symbols, but, like the physical disk info you can drag the mouse over these little dots and a tooltip will tell you more info about them (vdisk name, actual performance numbers, host name, wwn, etc.) d. Below this is the dashboard display (taken somewhat literally when coded up.) On this screen, total ISE is shown in pink, MRC1 is brown, and MRC2 is an off green. Think of the IOPS as a tachometer, the KBPS as a speedometer, and the transfer size (essentially kbps/iops) is the fuel gauge in the middle. The things that look like eyes are lights that get larger and brighter the higher the qdepth and latency gets (so if you see big red eyes it is really busy.) And of course the actual readings are shown to the right of that. Given that you know what you want to display, the only other major task in this design was to determine how to retrieve the data and analyze it. Retrieval is discussed further down in this document, but it is worth noting a few good starting points for accessing restful information from the ISE. Before reading the rest of this document, if you have an ISE available right now do the following: 1) From a web browser, enter either one of your ISEs IP addresses into the web browser address bar followed by a /query (i.e. 10.10.20.30/query). 2) You will get something that looks like the following: <?xml version="1.0" encoding="ISO8859-1" ?> - <array self="http://10.20.54.32/storage/arr ays/1BC10089"> <status value="0" string="Operational" /> <globalid>1BC10089</globalid> <id>20000014C367348C</id> <name>ISE</name> <serialnumber>1BC10089</serialnumber > <model>ISE1400</model> <vendor>XIOTECH</vendor> ...and so on… 3) Cut and paste the http string into the browser and press return. You will be requested for the Adminstrator login and password. NOTE: STAT5000 has the Administrator default password hard coded into it. 4) Take other http:// lines that you see in the resulting page and try looking at those Now things will make more sense when you look at what this code does (i.e. it is a big parsing, analysis, and display engine for some of this data.) Of note is that STAT5000 was actually written and tested by the developer while working from Florida and his mountain home in Georgia but while monitoring ISEs simultaneously in both Minnesota and Colorado to ensure that this would work fine over normal home internet connections. Using a 5 year old laptop to boot. It was also necessary to slow down the refresh rates from once a second to once every two seconds as it got hard to pause or grab information at the right moment when it was changing so fast, so atomic speed of retrieval wasn’t an issue for this type of application. Screen resolution needs to be 1280 by 950 at least. Some PCs exhibit no flicker at all, some see an occasional catchup flicker. Learning curve on the developers part who normally programs in C and C++ (who also happens to be writing this KB article). Before delving into the code itself, a few more points on the code design. AutoIt is a powerful language but it is single threaded from a programmer viewpoint. In a sense this is good because multi-threading can be somewhat of a headache for novice and expert programmers alike...often times producing unwanted results. Not something you want when programming around your corporate storage. However, multithreading is useful for ‘speeding’ up things (i.e. say you want instantaneous GUI response so that you can tooltip around existing data but also need to wait for xml data to be transferred from the ISEs). The way you accomplish this functionality using AutoIt is actually very easy. You simply: 1) write one autoit program that gathers the data (in this case it is called GET_XMLS.exe) and 2) write a main program (STAT5000.exe) that spawns off the GET_XMLS.exe whenever it needs data gathered, a. thereby using the OS for multitasking/threading b. and the filesystem as a ‘buffer’ mechanism as follows i. STAT5000 puts a list of ISE IP addresses in an INI file ii. then GET_XMLS 1. looks in that file for a list of IP addresses to scan 2. grabs all the requested restful xml data from each of these ISEs 3. saves that information into text files files, iii. then STAT5000 1. sees that the data has appeared, 2. reads the info in from the files, 3. And then kicks off another request after the desired sample dwell has expired Very simple and nothing steps on another process’s toes. A side benefit is that this means that future programs can be written to use GET_XMLS.exe and GET_XMLS.exe can be upgraded if necessary without recompiling all the programs that use it. The code for GET_XMLS.exe is only 300 lines or so of autoit source code, BTW and will be shown below. Also, STAT5000 is designed without any complex schemas or data structures. You will see a pretty flat structure when you look at the code and that was done entirely to keep things readable and ‘safe’. No pointers, strings are all essentially infinite length, no complex conditional code that you have to reread a number of times, etc. Also, this program is safe because it is ONLY monitoring an ISE…there is no configuration code active in this example at all (i.e. no volume deletes). During the entire development and subsequent testing of STAT5000 not a single ‘impact’ was ever seen on an ISE due to running this program. Now for the code. Sources for STAT5000 are currently about 1300 lines of code. The code that is provided with the SDK might vary a bit from this documents contents but hopefully the gist will carry forwards. The following section will go through the code from top to bottom and after that section will be one final section that summarizes Autoit. When developing with AutoIt, you will want to create an empty directory somewhere, put the source for STAT5000.au3 and GET_XMLS.au3 in that directory, build GET_XMLS to create GET_XMLS.exe (or just copy in the existing GET_XMLS.exe that is provided with the sdk) and then you can modify and either build the STAT5000.au3 or run it interactively. It doesn’t seem to run any slower interactively so is very usable either way. The Editor that comes with AutoIt has the capability of doing full syntax and rules checking on the code so is very handy as well. The Code: Each of the two executables (GET_XMLS.exe and STAT5000.exe) are standalone executables (i.e. just place them in a directory on a windows box and run them). If run without each other, STAT5000 will inform you that it needs to be able to see GET_XMLS.exe in the same directory and GET_XMLS.exe will just explain how to run it and how to construct the ini file it uses in case you have some standalone method you are testing (i.e. without using STAT5000). Again, STAT5000 will normally be all you run and it will call GET_XMLS.exe when needed. Sources for each executable are totally contained in the files GET_XMLS.au3 and STAT5000.au3 which are described in a bit more detail as follows. GET_XMLS.AU3: GET_XMLS.au3 was originally constructed as part of a test program called rest5000 (which accessed restful data and put it into a rudimentary report format). With STAT5000 it was modularized to work with both rest5000, STAT5000, and any other applications that might be developed. Quick comment on comments. Autoit has comments (anything that starts with a ;) and also has comment block capability (#cs/#ce): ;GET_XMLS for 5K - TRB 1/2010 #include <String.au3> #include #include #include #include #include #include <Constants.au3> <GuiEdit.au3> <Date.au3> <File.au3> <Array.au3> <Misc.au3> The include files above are all included with AutoIt. Interestingly they are just other source files so good tutorials also. $version = "1.0" $iniLocation = "torun.ini" global $ise_ips[64],$ip_cnt AutoItSetOption("WinDetectHiddenText",1) $ip_cnt = 0 I use a simple file blocking mechanism (get_xmls.blk) to prevent recursion. Notice that the onexit call ensure that the file is removed no matter how the program is terminated…although there is a slight hole if you were to power cycle your PC at just the right time (then you just need to manually delete the file). if fileexists("get_xmls.blk") then exit Opt("OnExitFunc","cleanup_on_exit") filewrite("get_xmls.blk",$version) Now just read the ini file to figure out what IP addresses to process, get all the xmls from them, and we are done so clean up read_ini() get_all_xmls() filedelete("get_xmls.blk") And that is the end of the program…somewhat like perl it just kind of ends when it doesn’t have anything but functions following it. Of course the program is in the functions that follow. Func read_ini() If (FileExists($iniLocation)) Then $ise_ips = _getISE_IPS() if(UBound($ise_ips) > 1) Then If (stringlen($ise_ips[1])>0) Then $ip_cnt=UBound($ise_ips) -1 Endif Endif Endif EndFunc Func get_all_xmls() for $i = 1 to UBound($ise_ips) - 1 ;for each IP address get_xmls($ise_ips[$i],$i) Next EndFunc The above logic is pretty self explanatory, but the bulk of the logic follows. The get_xmls routine is where the commandline is processed. From this it basically figures out what it has to grab in terms of xml data from each ISE. NOTE: get_xmls CAN be run standalone to just go out and grab data…if you run it without any options it will tell you what you need to do as shown in the MsgBox below…up to how to create the INI file if you hadn’t used stat5000 to do that for you. Aside from some convoluted logic that was placed in the code to ‘skip’ queries if they had previously been done during this session, the logic in get_xmls basically just calls GetAndSave to actually do the getting of the XML and then the saving of it to a file. Func get_xmls($ipstr,$iv) DIM $path_str[1] Local $i Local $todo="" $can_skip_query=0 if($CmdLine[0]==0) Then MsgBox(0,"get_xmls - Command Line Usage","get_xmls all - gets every xml the program knows about"&@CRLF&"get_xmls -f perf - gets perf xml using old query"&@CRLF&"get_xmls perf drives - gets perf and drive xmls"&@CRLF&@CRLF&"Options: perf cn ps vol bat host pool ise events dp drives net"&@CRLF&@CRLF&"NOTE: torun.ini file controls which MRCs are queried"&@CRLF&@CRLF&"Example torun.ini:"&@CRLF&"[IPS]"&@CRLF&"ISE_IPS=10 .64.50.118;10.64.50.115") exit elseIf($CmdLine[0]==1 AND stringinstr($CmdLine[1],"all")>0) Then $todo=",perf,cn,ps,vol,bat,host,pool,ise,ev ents,dp,drives,net" Else For $i = 1 To $CmdLine[0] if($CmdLine[$i]=="-f") Then $can_skip_query=1 Else $todo&=","&$CmdLine[$i] EndIf Next Endif if($can_skip_query == 1) Then $can_skip_query=0 if(fileexists("query_"&$ipstr&".hdr")) Then $query_resp=fileread("query_"&$ipstr&".hdr" ) if(StringInStr($query_resp," 200 OK")>0) Then $query_resp=fileread("query_"&$ipstr&".xml" ) if(stringlen($query_resp)>30) Then $can_skip_query=1 endif EndIf endif if(NOT ($can_skip_query == 1)) Then $query_resp = GetAndSave($ipstr,"","/query","query") ;figure out where things are EndIf if(StringInStr($query_resp," 200 OK")>0 OR $can_skip_query==1) Then ;did we get good response $path_str=_StringBetween($query_resp,$ipstr ,'"><Status') ;figure out path if NOT @error Then ;grab xml info and analyze it if(StringInStr($todo,",perf")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/performanc e","perf") if(stringlen($data_resp)<25) then return EndIf if(StringInStr($todo,",cn")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/controller s","mrcs") Endif if(StringInStr($todo,",ps")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/powersuppl ies","ps") Endif if(StringInStr($todo,",vol")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/volumes"," vols") Endif if(StringInStr($todo,",bat")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/batteries" ,"bats") Endif if(StringInStr($todo,",host")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/hosts","ho sts") Endif if(StringInStr($todo,",pool")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/pools","po ols") Endif if(StringInStr($todo,",ise")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"?all=yes"," ise") if(stringlen($data_resp)<25) then sleep(2000) $data_resp = GetAndSave($ipstr,$path_str[0],"?all=yes"," ise") if(stringlen($data_resp)<25) then sleep(4000) $data_resp = GetAndSave($ipstr,$path_str[0],"?all=yes"," ise") EndIf EndIf Endif if(StringInStr($todo,",event")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/files/even t","events") Endif if(StringInStr($todo,",dp")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/datapacs", "datapacs") Endif if(StringInStr($todo,",drive")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/drives","d rives") Endif if(StringInStr($todo,",net")) Then $data_resp = GetAndSave($ipstr,$path_str[0],"/network"," network") Endif EndIf EndIf EndFunc ; ; Grab the text found between the 'cnt'th occurance of string 'from' and string 'to' in string src ; …useful for xml (case insensitive search): $res=_TBetween($sub,"<SerialNumber>","</Ser ialNumber>") ; Func _TBetween($src,$from,$to,$cnt=1) $x=StringInStr($src,$from,0,$cnt) if($x=0) then return "-" $x=$x+stringlen($from) $y=StringInStr($src,$to,0,1,$x) if($y=0 OR $y<$x) then return "-" Return StringMid($src,$x,$y-$x) EndFunc Func GetAndSave($ipstr,$pathstr,$substr,$fname) $ret = GetRestData($ipstr,$pathstr&$substr) FileDelete($fname&"_"&$ipstr&".hdr") $y=StringInStr($ret,"<?xml") if($y>0) Then FileWrite($fname&"_"&$ipstr&".hdr",stringle ft($ret,$y-1)) Else FileWrite($fname&"_"&$ipstr&".hdr",$ret) EndIf if($y>0) Then FileDelete($fname&"_"&$ipstr&".xml") filewrite($fname&"_"&$ipstr&".xml",stringri ght($ret,stringlen($ret)-$y+1)) EndIf return $ret EndFunc Func _getISE_IPs() $iseipString = IniRead($iniLocation, "IPS", "ISE_IPS", "NotFound") $iseips = stringsplit($iseipString, ";") if $iseips == "NotFound" Then MsgBox(0, "Exception", "Could not find IPS Key 'ISE_IPS' in the configuration file") exit EndIf return $iseips EndFunc Oddly enough the logic below could be replaced by a single line in AutoIt but then we wouldn’t get the error checking and retry logic that is provided by this logic. The logic below takes things down to the lowest level you can go (i.e. essentially just TCPConnect, TCPSend, and TCPRecv logic. Nothing rocket science. Func GetRestData($host,$get_what,$port=80) Local $data = "" Opt("TCPTimeout",200) ; Set TCP Timeout to 200 ms TCPStartup() ; Initialize TCP $ip = TCPNameToIP($host) ; convert host name to ip if necessary $socket = TCPConnect($ip,$port) ; connect if($socket == -1) Then $data="TCPConnect Err="&@error else ; SEND HTTP GET $sent = TCPSend($socket,'GET '&$get_what&' HTTP/1.1'&@CRLF&'Host: '&$host&@CRLF&'Authorization: Basic YWRtaW5pc3RyYXRvcjphZG1pbmlzdHJhdG9y'&@CRLF &'Accept: */*'&@CRLF&'Connection: close'&@CRLF&@CRLF) if($sent==0) Then ; should be #bytes sent to socket $data="TCPSend Err="&@error&@CRLF else $begin=TimerInit() While 1 If TimerDiff($begin)>120000 Then _FileWriteLog("GET_XMLS.LOG","120 second timeout waiting for TCP data from "&$host) if($data=="") Then $data="TCPRecv Err=120 second program timeout"&@CRLF ExitLoop Endif $data &= TCPRecv($socket,1024) ; Recieve data If @error Then ; are we done yet? if($data=="") Then ; not expected ending so log sleep(100) $data &= TCPRecv($socket,1024) if @error Then if($data=="") Then $data="TCPRecv Err="&@error&@CRLF EndIf ExitLoop EndIf Else ExitLoop EndIf EndIf WEnd EndIf EndIf TCPCloseSocket($socket) TCPShutdown() return $data EndFunc Func cleanup_on_exit() ;Remove our busy lock since we are dying for whatever reason If(FileExists("get_xmls.blk")) Then FileDelete("get_xmls.blk") EndFunc STAT5000.AU3: STAT5000 uses (to an extreme) windows controls for its GUI logic. This has a side effect of not being able to resize the windows, but that is good because doing so would likely hide useful data (as tightly packed all of the information is in this display.) It also is best used in cases like this where you have just a single screen so you don’t spend all your time constructing and deconstruction controls. ;STAT5000 for 5K - TRB 2/2010 ;based loosely on REST5000 - TRB 1/2009 ;based loosely on VIEW5000 - TRB 12/2009 ;which is based loosely on SHOW5000 11/2009 ;which mimics capability of SHOWALL - later half 2009 ; Description: ; Full logic writtin in autoit to: ; 1) gather restful info (xml data) from MRCs. Migrated this logic to get_xmls.au3. Standard now in get_xmls.au3. ; 2) analyze xml data and present the results to the user in view5000 format, but optimized to show stats and perf ; 3) also make the information available in: ; a) raw data (xml) retrieved files of format [type]_[ip].xml (i.e. drives_10.10.20.30.xml) ; 4) provide polling logic to retrieve data on a timed basis ; 5) GUI (initially) will simply be view5000 format. Intent is something neat to watch (and to see performance). ; 6) add logic to change polling rate (via button cycle) ; 7) add logic to capture all data into a csv file for each sample interval ; 8) add logic to stop/start capture ; 9) add logic to age capture data and then start capturing to an empty file #include <String.au3> #include <Constants.au3> #include <GuiConstants.au3> #include <GuiEdit.au3> #include <Date.au3> #include <Timers.au3> #include <GUIListView.au3> #include <WinAPI.au3> #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <GUIComboBox.au3> #include <ListViewConstants.au3> #include #include #include #include #include #include <WindowsConstants.au3> <File.au3> <Array.au3> <Misc.au3> <Math.au3> <StaticConstants.au3> You will note that the following line is NOT in the get_xmls source…when get_xmls.exe runs you will see it on your lower right screen icon tray…you can actually pause it (or kill it) in that tray if you want to. No need for that in a GUI since the GUI is on the screen so this line allows you to hide it from the tray. Opt("TrayIconHide", 1) ; don't put this app icon in the tray Global $dll = DllOpen("user32.dll") ; ; define some 'constants' ; $VERSION = "1.0" $INILOCATION = "torun.ini" Global $MWIDTH=414,$MHIGH=288,$MCNT=8 ; height, width, and number of 'ise' windows Global $DO_HOSTS=1,$DO_VOLS=0 Global $INIT=1,$REFRESH=0 Global $MAXIOPS=10000,$MAXKBPS=200000,$MAXQD=29,$M AXIOSZ=1024 Global $MAX_ISES=17 ; actually this is maximum ises + 1 Global $MAX_VOLS=512 ; overkill since current is 240 Global $MAX_HOSTS=256 ; overkill, but unsure of max Global $MAX_DISKS=40 ; max disks per ise Global $MAX_EVENTS=512 ; max events gathered ; ; Window forms and buttons ; Global $main_form,$listview Global $add_input,$sample_button,$delete_button,$a dd_button,$agecaps_button,$stopstartcaps_bu tton Global $hListView,$lastdd=-1 Global $hEdit, $hDC, $hBrush, $Item = -1, $SubItem = 0 Global $Style = BitOR($WS_CHILD, $WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT) Global $iLastItem = -1, $iLastsubitemNR = 1 Global $doing_get = 0 ; reentrancy check for get_xmls call Global $cwnd ; current window handle (used by subs) Global $passcnt=0 ; tracks frequency of slow data gathers Global $capture_enabled=0 ; used to start and stop csv data capturing Global $gather_timer ; pointer to timer handle Global $timestart = TimerInit() ; get timer ticking and baseline Global $begin ; tracks timer differentials Global $L_NUM_BAD,$L_NUM_WARN ; color (green/yellow/red) trackers Dim $host_or_vol[$MAX_ISES] ; tracks what we are looking at (host hbas or volumes) ; ; Following is what we directly use and retrieve via restful calls ; NOTE: not everything in this Global list is necessarily retrieved or used by this APP ; ; for the ISE itself Global $ise_ips[$MAX_ISES],$ip_cnt Global $ise_iops,$ise_kbps,$ise_qd,$ise_readpct,$i se_readlat,$ise_writelat,$ise_xfersize Global $ise_sts,$ise_detail,$ise_sn,$ise_temp,$ise _dhcp,$ise_wol ; for the mrcs Global $cn1_iops,$cn1_kbps,$cn1_qd,$cn1_readpct,$c n1_readlat,$cn1_writelat,$cn1_xfersize Global $cn2_iops,$cn2_kbps,$cn2_qd,$cn2_readpct,$c n2_readlat,$cn2_writelat,$cn2_xfersize Global $cn1_ip,$cn1_sts,$cn1_detail,$cn1_sn,$cn1_f wver,$cn1_temp,$cn1_fcspeed,$cn1_lipcnt,$cn 1_noscnt Global $cn2_ip,$cn2_sts,$cn2_detail,$cn2_sn,$cn2_f wver,$cn2_temp,$cn2_fcspeed,$cn2_lipcnt,$cn 2_noscnt Global $cn1_conn,$cn2_conn ; for the power supplies Global $ps1_sts,$ps1_detail,$ps1_sn,$ps1_temp,$ps1 _bl1_sts,$ps1_bl2_sts Global $ps2_sts,$ps2_detail,$ps2_sn,$ps2_temp,$ps2 _bl1_sts,$ps2_bl2_sts ; for the batteries Global $bat1_sts,$bat1_detail,$bat1_sn,$bat1_temp, $bat1_charge_sts,$bat1_charge_detail,$bat1_ charge_left Global $bat2_sts,$bat2_detail,$bat2_sn,$bat2_temp, $bat2_charge_sts,$bat2_charge_detail,$bat2_ charge_left ; for the datapacs Global $dp1_sts,$dp1_detail,$dp1_sn,$dp1_temp,$dp1 _peaktemp,$dp1_poolnum,$dp1_health,$dp1_fwv er,$dp1_model,$dp1_sparelevel,$dp1_capacity Global $dp2_sts,$dp2_detail,$dp2_sn,$dp2_temp,$dp2 _peaktemp,$dp2_poolnum,$dp2_health,$dp2_fwv er,$dp2_model,$dp2_sparelevel,$dp2_capacity Global $dp_type,$dp_cg ; for the pools Global $pool1_sts,$pool1_detail,$pool1_avail,$pool 1_used,$pool1_r0,$pool1_r1,$pool1_r5 Global $pool2_sts,$pool2_detail,$pool2_avail,$pool 2_used,$pool2_r0,$pool2_r1,$pool2_r5 Global $r5_cnt,$r1_cnt,$r0_cnt,$numdrives[$MAX_ISE S] Dim $numevent,$event_date[$MAX_EVENTS],$event_t ime[$MAX_EVENTS],$event_desc[$MAX_EVENTS],$ event_type[$MAX_EVENTS] ; for the volumes (luns) presented to servers Dim $numvol[$MAX_ISES],$vol_sts[$MAX_ISES][$MAX _VOLS],$vol_name[$MAX_ISES][$MAX_VOLS],$vol _policy[$MAX_ISES][$MAX_VOLS] Dim $vol_size[$MAX_ISES][$MAX_VOLS],$vol_locali d[$MAX_ISES][$MAX_VOLS],$vol_level[$MAX_ISE S][$MAX_VOLS] Dim $vol_gid[$MAX_ISES][$MAX_VOLS],$vol_type[$M AX_ISES][$MAX_VOLS],$vol_mirror[$MAX_ISES][ $MAX_VOLS],$v_h[$MAX_ISES][$MAX_VOLS] Dim $v_ss[$MAX_ISES][$MAX_VOLS],$wb_cnt Dim $vol_iops[$MAX_ISES][$MAX_VOLS],$vol_kbps[$ MAX_ISES][$MAX_VOLS],$vol_riops[$MAX_ISES][ $MAX_VOLS] Dim $vol_wiops[$MAX_ISES][$MAX_VOLS],$vol_rkbps [$MAX_ISES][$MAX_VOLS],$vol_wkbps[$MAX_ISES ][$MAX_VOLS] Dim $vol_readpct[$MAX_ISES][$MAX_VOLS],$vol_avg xfrsize[$MAX_ISES][$MAX_VOLS],$vol_qd[$MAX_ ISES][$MAX_VOLS] Dim $vol_readlat[$MAX_ISES][$MAX_VOLS],$vol_wri telat[$MAX_ISES][$MAX_VOLS] Dim $vol_qdmax[$MAX_ISES][$MAX_VOLS],$vol_rlatm ax[$MAX_ISES][$MAX_VOLS],$vol_wlatmax[$MAX_ ISES][$MAX_VOLS] ; for the disks themselves Dim $numdrive,$d_iops[$MAX_ISES][$MAX_DISKS],$d _kbps[$MAX_ISES][$MAX_DISKS],$d_qd[$MAX_ISE S][$MAX_DISKS] Dim $d_readpct[$MAX_ISES][$MAX_DISKS],$d_readla t[$MAX_ISES][$MAX_DISKS],$d_writelat[$MAX_I SES][$MAX_DISKS] Dim $d_gotit[$MAX_ISES][$MAX_DISKS],$d_sn[$MAX_ ISES][$MAX_DISKS],$d_sts[$MAX_ISES][$MAX_DI SKS],$d_detail[$MAX_ISES][$MAX_DISKS] Dim $d_capacity[$MAX_ISES][$MAX_DISKS],$d_fwver [$MAX_ISES][$MAX_DISKS],$d_prodid[$MAX_ISES ][$MAX_DISKS] Dim $d_temp[$MAX_ISES][$MAX_DISKS],$d_id[$MAX_I SES][$MAX_DISKS],$d_rc[$MAX_ISES][$MAX_DISK S] Dim $d_5v[$MAX_ISES][$MAX_DISKS],$d_12v[$MAX_IS ES][$MAX_DISKS],$d_dp[$MAX_ISES][$MAX_DISKS ],$d_position[$MAX_ISES][$MAX_DISKS] ; hosts Global $numhosts[$MAX_ISES],$host_id[$MAX_ISES][$M AX_HOSTS],$host_wwn[$MAX_ISES][$MAX_HOSTS], $host_name[$MAX_ISES][$MAX_HOSTS] Dim $host_type[$MAX_ISES][$MAX_HOSTS],$host_iop s[$MAX_ISES][$MAX_HOSTS],$host_kbps[$MAX_IS ES][$MAX_HOSTS] Dim $host_riops[$MAX_ISES][$MAX_HOSTS],$host_wi ops[$MAX_ISES][$MAX_HOSTS],$host_rkbps[$MAX _ISES][$MAX_HOSTS] Dim $host_wkbps[$MAX_ISES][$MAX_HOSTS],$host_re adpct[$MAX_ISES][$MAX_HOSTS],$host_avgxfrsi ze[$MAX_ISES][$MAX_HOSTS] Dim $host_qd[$MAX_ISES][$MAX_HOSTS],$host_readl at[$MAX_ISES][$MAX_HOSTS],$host_writelat[$M AX_ISES][$MAX_HOSTS] Dim $host_qdmax[$MAX_ISES][$MAX_HOSTS],$host_rl atmax[$MAX_ISES][$MAX_HOSTS],$host_wlatmax[ $MAX_ISES][$MAX_HOSTS] ; following are control tags (used to display/hide/etc a ControlClick Dim $G_TOP[$MAX_ISES],$G_CN1[$MAX_ISES],$G_CN2[ $MAX_ISES],$G_DP1[$MAX_ISES],$G_DP2[$MAX_IS ES] Dim $G_IO_L[$MAX_ISES],$G_IO_I[$MAX_ISES],$G_IO _1[$MAX_ISES],$G_IO_2[$MAX_ISES] Dim $G_KB_L[$MAX_ISES],$G_KB_I[$MAX_ISES],$G_KB _1[$MAX_ISES],$G_KB_2[$MAX_ISES] Dim $G_QD_L[$MAX_ISES],$G_QD_I[$MAX_ISES],$G_QD _1[$MAX_ISES],$G_QD_2[$MAX_ISES] Dim $G_MXLAT_L[$MAX_ISES],$G_MXLAT_I[$MAX_ISES] ,$G_MXLAT_1[$MAX_ISES],$G_MXLAT_2[$MAX_ISES ] Dim $G_RWPCT_L[$MAX_ISES],$G_RWPCT_I[$MAX_ISES] ,$G_RWPCT_1[$MAX_ISES],$G_RWPCT_2[$MAX_ISES ] Dim $aa[$MAX_ISES] ;ise subwindow control tag ;yes, this actually works but minimal checking: InetGet("http://10.64.50.118/query","toddte st.xml") The above variables are a bit overkill for this application (currently) but are included to give you an idea of some of the other things that you can easily gather. The following few lines actually comprise the entire ‘mainline’ of the code..basically just a check to make sure you have a compiled version of get_xmls.exe and then grab whatever ISE IP addresses we might have, setup the windows GUI stuff and jump into the main loop. ;*********START OF PROGRAM MAIN CODE************ If NOT fileexists("get_xmls.exe") Then MsgBox(0,"ERROR!","FILE: get_xmls.exe missing. You need this for Cortex Polling!") exit EndIf ; Gather up the MRC IP addresses read_ini() window_setup("Emprise 5000 Stat Watcher, Version "&$VERSION) draw_cheat_sheet() draw_ise_windows($INIT) main_loop() gui_exit() ;**********END OF PROGRAM MAIN CODE************** ; ----------------------------------------------------------------------------; FUNCTIONS ; ----------------------------------------------------------------------------; ; program stays in the following loop until user closes app ; all processing is either a result of user mouse movement, mouse clicks, keyboard entry, ; or timer countdowns that kick off xml data gathering and processing (which then induce screen updates). ; Func main_loop() setup_listview() $gather_timer=_Timer_SetTimer($main_form,20 00,"_get_xmls") _get_xmls(0,0,0,0) GUICtrlSetState($add_input, $GUI_FOCUS) ;so that when we type an IP and press return we get 'Add' While 1 $nMsg = GUIGetMsg() $pos=GUIGetCursorInfo($main_form) ;NOTE: MouseGetPos is relative to entire screen, this is 'local' show_tool_tip($pos) If _IsPressed("2E", $dll) Then _GUICtrlListView_DeleteItemsSelected($hList View) GUICtrlSetData($listview, "#|IP ADDRESSES ("&_GUICtrlListView_GetItemCount($listview) &")") save_ini() EndIf Switch $nMsg Case $GUI_EVENT_CLOSE save_ini() gui_exit() Exit case $agecaps_button do_age_captures() GUICtrlSetState($add_input, $GUI_FOCUS) case $stopstartcaps_button do_stopstart_captures() if $capture_enabled Then $nextbut="Stop Capture" GUICtrlSetColor($stopstartcaps_button,0x801 080) Else $nextbut="Start Capture" GUICtrlSetColor($stopstartcaps_button,0x000 000) Endif GUICtrlSetData($stopstartcaps_button,$nextb ut) GUICtrlSetState($add_input, $GUI_FOCUS) case $sample_button $var=0 $curbut=GUICtrlRead($sample_button) if $curbut<>"Sample=off" Then _Timer_KillTimer($main_form,$gather_timer) if $curbut="Sample=1hr" Then $nextbut="Sample=off" GUICtrlSetData($sample_button,$nextbut) elseif $curbut="Sample=off" Then $nextbut="Sample=2s" $var=2000 elseif $curbut="Sample=2s" Then $nextbut="Sample=10s" $var=10000 elseif $curbut="Sample=10s" Then $nextbut="Sample=1m" $var=60000 elseif $curbut="Sample=1m" Then $nextbut="Sample=10m" $var=600000 elseif $curbut="Sample=10m" Then $nextbut="Sample=1hr" $var=3600000 endif if($var>0) Then $gather_timer=_Timer_SetTimer($main_form,$v ar,"_get_xmls") if @error OR $gather_timer=0 Then ContinueLoop _get_xmls(0,0,0,0) GUICtrlSetData($sample_button,$nextbut) GUICtrlSetState($add_input, $GUI_FOCUS) EndIf Case $delete_button _GUICtrlListView_DeleteItemsSelected($hList View) GUICtrlSetData($listview, "#|IP ADDRESSES ("&_GUICtrlListView_GetItemCount($listview) &")") save_ini() Case $add_button $iptest=GUICtrlRead($add_input) If $iptest = "" OR StringInstr($iptest,",")<>0 OR NOT StringRegExp($iptest,"(\d\d?\d?).(\d\d?\d?) .(\d\d?\d?).(\d{1,})$",0) Then MsgBox(16,"Enter a Valid IP address","Expected input is something like 10.64.100.101") Else $addnum = _GUICtrlListView_GetItemCount($listview) _GUICtrlListView_AddItem($hListView, $addnum+1, 0) _GUICtrlListView_AddSubItem($hListView, $addnum, GUICtrlRead($add_input), 1, 1) _GUICtrlListView_EnsureVisible($hListView, $addnum) GUICtrlSetData($listview, "#|IP ADDRESS: ("&_GUICtrlListView_GetItemCount($listview) &")") GUICtrlSetData($add_input, "") GUICtrlSetState($add_input, $GUI_FOCUS) save_ini() $passcnt=0 EndIf EndSwitch WEnd _Timer_KillAllTimers($main_form) EndFunc ; ; Get xml data via restful interface and then process it. ; NOTE: the get process calls another autoit program called get_xmls so that we get multi-threading ; without the normal pain of multithreading ; Func _get_xmls($hWnd,$Msg,$iIDTimer,$dwTime) if($doing_get==1) THen Return $doing_get=1 if($ip_cnt>0) Then if(NOT fileexists("get_xmls.blk")) Then sleep(100) if(NOT fileexists("get_xmls.blk")) Then draw_ise_windows($REFRESH) if(mod($passcnt,300)<>0) Then Run(@ComSpec & " /c get_xmls.exe -f perf",@ScriptDir,@SW_HIDE) else Run(@ComSpec & " /c get_xmls.exe perf ise drive",@ScriptDir,@SW_HIDE) endif $passcnt=$passcnt+1 Endif Endif EndIf $doing_get=0 EndFunc Func process_xmls($ipstr,$wh) local $inp,$logise="",$logcn1="",$logcn2="",$logd rives="" $inp=FileRead("perf_"&$ipstr&".xml") if(stringlen($inp)>100) Then $sub=_TBetween($inp,"Element self","</Element") if(stringlen($sub)<20) Then $sub=_TBetween($inp,"Array self","</Array") $ise_iops=_TBetween($sub,"<TotalIOPS>","</T otalIOPS>") $ise_kbps=_TBetween($sub,"<TotalKBPS>","</T otalKBPS>") $ise_qd=_TBetween($sub,"<QueueDepth>","</Qu eueDepth>") $ise_readpct=_TBetween($sub,"<ReadPercent>" ,"</ReadPercent>") $ise_readlat=_TBetween($sub,"<ReadLatency>" ,"</ReadLatency>") $ise_writelat=_TBetween($sub,"<WriteLatency >","</WriteLatency>") $ise_xfersize=_TBetween($sub,"<AvgXfrSize>" ,"</AvgXfrSize>") $sub=_TBetween($inp,"controllers/1","</cont roller") $cn1_iops=_TBetween($sub,"<TotalIOPS>","</T otalIOPS>") $cn1_kbps=_TBetween($sub,"<TotalKBPS>","</T otalKBPS>") $cn1_qd=_TBetween($sub,"<QueueDepth>","</Qu eueDepth>") $cn1_readpct=_TBetween($sub,"<ReadPercent>" ,"</ReadPercent>") $cn1_readlat=_TBetween($sub,"<ReadLatency>" ,"</ReadLatency>") $cn1_writelat=_TBetween($sub,"<WriteLatency >","</WriteLatency>") $cn1_xfersize=_TBetween($sub,"<AvgXfrSize>" ,"</AvgXfrSize>") $sub=_TBetween($inp,"controllers/2","</cont roller") $cn2_iops=_TBetween($sub,"<TotalIOPS>","</T otalIOPS>") $cn2_kbps=_TBetween($sub,"<TotalKBPS>","</T otalKBPS>") $cn2_qd=_TBetween($sub,"<QueueDepth>","</Qu eueDepth>") $cn2_readpct=_TBetween($sub,"<ReadPercent>" ,"</ReadPercent>") $cn2_readlat=_TBetween($sub,"<ReadLatency>" ,"</ReadLatency>") $cn2_writelat=_TBetween($sub,"<WriteLatency >","</WriteLatency>") $cn2_xfersize=_TBetween($sub,"<AvgXfrSize>" ,"</AvgXfrSize>") $numdrive=0 for $idx=1 to 40 $sub=_TBetween($inp,"drives/"&$idx,"</drive ") if Stringlen($sub)>20 then $numdrive=$numdrive+1 $d_gotit[$wh][$idx-1]=1 $d_iops[$wh][$idx1]=_TBetween($sub,"<TotalIOPS>","</TotalIOP S>") $d_kbps[$wh][$idx1]=_TBetween($sub,"<TotalKBPS>","</TotalKBP S>") $d_qd[$wh][$idx1]=_TBetween($sub,"<QueueDepth>","</QueueDe pth>") $d_readpct[$wh][$idx1]=_TBetween($sub,"<ReadPercent>","</ReadPe rcent>") $d_readlat[$wh][$idx1]=_TBetween($sub,"<ReadLatency>","</ReadLa tency>") $d_writelat[$wh][$idx1]=_TBetween($sub,"<WriteLatency>","</Write Latency>") $logdrives=$logdrives&","&$d_iops[$wh][$idx -1]&","&$d_kbps[$wh][$idx1]&","&$d_qd[$wh][$idx1]&","&$d_readpct[$wh][$idx1]&","&$d_readlat[$wh][$idx1]&","&$d_writelat[$wh][$idx-1] else $d_gotit[$wh][$idx-1]=0 endif Next $sub2=_TBetween($inp,"<volumes","</volumes" ) $idx=0 $sub=_Tbetween($sub2,"<volume","</volume",$ idx+1) While $sub<>"-" $idx=$idx+1 $vol_iops[$wh][$idx1]=_TBetween($sub,"<TotalIOPS>","</TotalIOP S>") $vol_kbps[$wh][$idx1]=_TBetween($sub,"<TotalKBPS>","</TotalKBP S>") $vol_riops[$wh][$idx1]=_TBetween($sub,"<ReadIOPS>","</ReadIOPS> ") $vol_rkbps[$wh][$idx1]=_TBetween($sub,"<ReadKBPS>","</ReadKBPS> ") $vol_wiops[$wh][$idx1]=_TBetween($sub,"<WriteIOPS>","</WriteIOP S>") $vol_wkbps[$wh][$idx1]=_TBetween($sub,"<WriteKBPS>","</WriteKBP S>") $vol_qd[$wh][$idx1]=_TBetween($sub,"<QueueDepth>","</QueueDe pth>") $vol_avgxfrsize[$wh][$idx1]=_TBetween($sub,"<avgxfrsize>","</avgxfrs ize>") $vol_readpct[$wh][$idx1]=_TBetween($sub,"<ReadPercent>","</ReadPe rcent>") $vol_readlat[$wh][$idx1]=_TBetween($sub,"<ReadLatency>","</ReadLa tency>") $vol_writelat[$wh][$idx1]=_TBetween($sub,"<WriteLatency>","</Write Latency>") $vol_rlatmax[$wh][$idx1]=_TBetween($sub,"<readlatencymax>","</rea dlatencymax>") $vol_wlatmax[$wh][$idx1]=_TBetween($sub,"<writelatencymax>","</wr itelatencymax>") $vol_qdmax[$wh][$idx1]=_TBetween($sub,"<QueueDepthmax>","</Queu eDepthmax>") $vol_name[$wh][$idx1]=_TBetween($sub,"<name>","</name") $sub=_Tbetween($sub2,"<volume","</volume",$ idx+1) WEnd $numvol[$wh]=$idx $sub2=_TBetween($inp,"<hosts","</hosts") $idx=0 $sub3=_TBetween($sub2,"<host","</host",$idx +1) While $sub3<>"-" $h_name=_TBetween($sub3,"<name>","</name") $tcnt=1 $sub=_TBetween($sub3,"<endpoint ","</endpoint",$tcnt) While $sub<>"-" $tcnt=$tcnt+1 $idx=$idx+1 $host_name[$wh][$idx-1]=$h_name $host_wwn[$wh][$idx1]=_TBetween($sub3,"<wwn>","</wwn") if($host_wwn[$wh][$idx-1]="-") Then $host_wwn[$wh][$idx1]=_TBetween($sub3,"<globalid>","</globalid ") EndIf $host_iops[$wh][$idx1]=_TBetween($sub,"<TotalIOPS>","</TotalIOP S>") $host_kbps[$wh][$idx1]=_TBetween($sub,"<TotalKBPS>","</TotalKBP S>") $host_riops[$wh][$idx1]=_TBetween($sub,"<ReadIOPS>","</ReadIOPS> ") $host_rkbps[$wh][$idx1]=_TBetween($sub,"<ReadKBPS>","</ReadKBPS> ") $host_wiops[$wh][$idx1]=_TBetween($sub,"<WriteIOPS>","</WriteIOP S>") $host_wkbps[$wh][$idx1]=_TBetween($sub,"<WriteKBPS>","</WriteKBP S>") $host_qd[$wh][$idx1]=_TBetween($sub,"<QueueDepth>","</QueueDe pth>") $host_avgxfrsize[$wh][$idx1]=_TBetween($sub,"<avgxfrsize>","</avgxfrs ize>") $host_readpct[$wh][$idx1]=_TBetween($sub,"<ReadPercent>","</ReadPe rcent>") $host_readlat[$wh][$idx1]=_TBetween($sub,"<ReadLatency>","</ReadLa tency>") $host_writelat[$wh][$idx1]=_TBetween($sub,"<WriteLatency>","</Write Latency>") $host_rlatmax[$wh][$idx1]=_TBetween($sub,"<readlatencymax>","</rea dlatencymax>") $host_wlatmax[$wh][$idx1]=_TBetween($sub,"<writelatencymax>","</wr itelatencymax>") $host_qdmax[$wh][$idx1]=_TBetween($sub,"<QueueDepthmax>","</Queu eDepthmax>") $sub=_TBetween($sub3,"<endpoint ","</endpoint",$tcnt) WEnd $sub3=_TBetween($sub2,"<host","</host",$idx +1) Wend $numhosts[$wh]=$idx Else return 0 EndIf $inp=FileRead("ise_"&$ipstr&".xml") if(stringlen($inp)>100) Then $ise_sts=_TBetween($inp,' string="','"><Details value') $ise_detail=_TBetween($inp,"<detail>","</de tail>") $ise_sn=_TBetween($inp,"<SerialNumber>","</ SerialNumber>") $cn1_ip=_TBetween($inp,"<IpAddress1>","</Ip Address1>") $cn2_ip=_TBetween($inp,"<IpAddress2>","</Ip Address2>") $ise_temp=_TBetween($inp,'<Temperature value="','"') $sub=_TBetween($inp,"/controllers/1","</con troller>") $cn1_sts=_TBetween($sub,'string="','"') $sub=_TBetween($inp,"/controllers/2","</con troller>") $cn2_sts=_TBetween($sub,'string="','"') $sub=_TBetween($inp,"/datapacs/1","</datapa c>") if($sub=="-") Then $sub=_TBetween($inp,"/media/1","</media>") $dp1_sts=_TBetween($sub,'string="','"') $sub=_TBetween($inp,"/datapacs/2","</datapa c>") if($sub=="-") Then $sub=_TBetween($inp,"/media/2","</media>") $dp2_sts=_TBetween($sub,'string="','"') $sub=_TBetween($inp,"/powersupplies/1","</p owersupply>") $ps1_sts=_TBetween($sub,'string="','"') $sub=_TBetween($inp,"/powersupplies/2","</p owersupply>") $ps2_sts=_TBetween($sub,'string="','"') $sub=_TBetween($inp,"/batteries/1","</batte ry>") $bat1_sts=_TBetween($sub,'string="','"') $sub=_TBetween($inp,"/batteries/2","</batte ry>") $bat2_sts=_TBetween($sub,'string="','"') $logise=","&$ise_sn&","&$ise_sts&","&int(($ ise_temp*9/5)+32)&","&$ise_iops&","&$ise_kb ps&","&$ise_qd&","& _ $ise_readlat&","&$ise_writelat&","&$ise_rea dpct&","&$ise_xfersize $logcn1=","&$cn1_sts&","&$cn1_iops&","&$cn1 _kbps&","&$cn1_qd&","& _ $cn1_readlat&","&$cn1_writelat&","&$cn1_rea dpct&","&$cn1_xfersize $logcn2=","&$cn2_sts&","&$cn2_iops&","&$cn2 _kbps&","&$cn2_qd&","& _ $cn2_readlat&","&$cn2_writelat&","&$cn2_rea dpct&","&$cn2_xfersize Else return 0 endif $inp=FileRead("query_"&$ipstr&".xml") if(stringlen($inp)>100) Then $ise_wwn=_TBetween($inp,' string="','"><Details value') $ise_date=_TBetween($inp,'date="','" ') $ise_time=_TBetween($inp,'time="','">') $sub=_TBetween($inp,"controllers/1","/contr oller") if(stringlen($sub)>100) Then $cn1_fwver=_TBetween($inp,"<FwVersion>","</ FwVersion>") EndIf $sub=_TBetween($inp,"controllers/2","/contr oller") if(stringlen($sub)>100) Then $cn2_fwver=_TBetween($inp,"<FwVersion>","</ FwVersion>") EndIf Else return 0 endif $inp=FileRead("drives_"&$ipstr&".xml") $numdrives[$wh]=0 if(stringlen($inp)>100) Then do $sub=_TBetween($inp,"<drive ","</drive>",($numdrives[$wh]+1)) if stringlen($sub)>100 Then $d_sts[$wh][$numdrives[$wh]]=_TBetween($sub ,'Status string="','">') $d_sn[$wh][$numdrives[$wh]]=_TBetween($sub, "<SerialNumber>","</SerialNumber>") $d_fwver[$wh][$numdrives[$wh]]=_TBetween($s ub,"<FwVersion>","</FwVersion>") $d_dp[$wh][$numdrives[$wh]]=_TBetween($sub, "datapacs/",'"') if($d_dp[$wh][$numdrives[$wh]]=="-") Then $d_dp[$wh][$numdrives[$wh]]=_TBetween($sub, "media/",'"') endif if($d_sts[$wh][$numdrives[$wh]]=="Operation al" AND $d_dp[$wh][$numdrives[$wh]]==1) Then $dp1_fwver=$d_fwver[$wh][$numdrives[$wh]] if($d_sts[$wh][$numdrives[$wh]]=="Operation al" AND $d_dp[$wh][$numdrives[$wh]]==2) Then $dp2_fwver=$d_fwver[$wh][$numdrives[$wh]] $d_capacity[$wh][$numdrives[$wh]]=_TBetween ($sub,"<Capacity>","</Capacity>") $d_temp[$wh][$numdrives[$wh]]=_TBetween($su b,'<Temperature value="','">') $d_5v[$wh][$numdrives[$wh]]=_TBetween($sub, "<Range5V>","</Range5V") $d_12v[$wh][$numdrives[$wh]]=_TBetween($sub ,"<Range12V>","</Range12V") $d_rc[$wh][$numdrives[$wh]]=_TBetween($sub, "<ReducedCapacity>","</ReducedCapacity>") $d_id[$wh][$numdrives[$wh]]=_TBetween($sub, "<Position>","</Position>") $d_prodid[$wh][$numdrives[$wh]]=_TBetween($ sub,"<ProductId>","</ProductId>") $d_detail[$wh][$numdrives[$wh]]=_TBetween($ sub,"<Detail>","</Detail>") $d_position[$wh][$numdrives[$wh]]=_TBetween ($sub,"<Position>","</Position>") $numdrives[$wh]=$numdrives[$wh]+1 Else ExitLoop EndIf until $numdrives[$wh]=40 EndIf if $capture_enabled Then if Not fileexists("statperf_"&$ipstr&".csv") Then $prline="date/time,ise sn,ise status,ise temp,iops ise,kbps ise,qd ise,read latency ise,write latency ise,read percent ise,xfer size ise,"& _ "status cn1,iops cn1,kbps cn1,qd cn1,read latency cn1,write latency cn1,read percent cn1,xfer size cn1,"& _ "status cn2,iops cn2,kbps cn2,qd cn2,read latency cn2,write latency cn2,read percent cn2,xfer size cn2" for $i=1 to $numdrives[$wh] $prline=$prline&",iops slot"&$i&",kbps slot"&$i&",qd slot"&$i&",read percent slot"&$i&",read latency slot"&$i&",write latency slot" Next FileWriteLine("statperf_"&$ipstr&".csv",$pr line) Endif ;and log one sample line FileWriteLine("statperf_"&$ipstr&".csv",'"' &@YEAR&"/"&@MON&"/"&@MDAY&""&@HOUR&":"&@MIN&":"&@SEC&'"'&$logise&$logc n1&$logcn2&$logdrives) EndIf return 1 EndFunc ; ; logic toggles state of capture and ages captures to a depth of 8 ; Func do_stopstart_captures() $capture_enabled=1-$capture_enabled EndFunc Func do_age_captures() local $i,$j for $i = 1 to 8 if($i<UBound($ise_ips)) Then ; first age out old stuff if FileExists("statperf_"&$ise_ips[$i]&".csv") Then for $j=8 to 1 step -1 if FileExists("statperf_bu_"&$j&"_"&$ise_ips[$ i]&".csv") Then FileMove("statperf_bu_"&$j&"_"&$ise_ips[$i] &".csv","statperf_bu_"&$j+1&"_"&$ise_ips[$i ]&".csv") EndIf Next FileMove("statperf_"&$ise_ips[$i]&".csv","s tatperf_bu_1_"&$ise_ips[$i]&".csv") EndIf EndIf Next EndFunc ; ; This logic just grabs the text found between the 'cnt'th occurance of string 'from' and string 'to' in string src ; i.e. useful for xml (case insensitive search): $res=_TBetween($sub,"<SerialNumber>","</Ser ialNumber>") ; Func _TBetween($src,$from,$to,$cnt=1) $x=StringInStr($src,$from,0,$cnt) if($x=0) then return "-" $x=$x+stringlen($from) $y=StringInStr($src,$to,0,1,$x) if($y=0 OR $y<$x) then return "-" Return StringMid($src,$x,$y-$x) EndFunc ; ; Following logic reads ip addresses from the ini file and updates the ini file based on list box contents ; Func _getISE_IPs() $iseipString = IniRead($INILOCATION, "IPS", "ISE_IPS", "NotFound") $iseips = stringsplit($iseipString, ";") if $iseips == "NotFound" Then MsgBox(0, "Exception", "Could not find IPS Key 'ISE_IPS' in the configuration file") exit EndIf return $iseips EndFunc Func read_ini() $ip_cnt=0 If (FileExists($INILOCATION)) Then $ise_ips = _getISE_IPS() if(UBound($ise_ips) > 1) Then If (stringlen($ise_ips[1])>0) Then $ip_cnt=UBound($ise_ips) -1 Endif Endif Endif EndFunc Func save_ini() $ssdata="" for $i =1 to _GuiCtrlListView_GetItemCount($listview) if(stringlen(_GuiCtrlListView_GetItemText($ hListView,$i-1,1)) > 7) Then if(stringRegExp(_GuiCtrlListView_GetItemTex t($hListView,$i1,1),"(\d\d?\d?).(\d\d?\d?).(\d\d?\d?).(\d{ 1,})$",0)) Then if $ssdata == "" then $ssdata = "ISE_IPS=" & $ssdata & _GUICtrlListView_GetItemText($hListView,$i1,1) else $ssdata = $ssdata & ";" & _GUICtrlListView_GetItemText($hListView,$i1,1) EndIf Endif Endif Next iniWriteSection($INILOCATION,"IPS",$ssdata) read_ini() EndFunc ; ; and the rest of this file is screen drawing and handling ; Tooltips are neat and pretty easy to implement. In the main program loop this logic is called every time there is ANY event (so lots). Not the most efficient approach but it gives you a nice fast tooltip feel as you slide the mouse around the display. The logic below will either show the tooltip or clear it so it is designed to disappear when the mouse leaves a region. Having a 1 second compile and try cycle using the interactive mode of AutoIt allows you to create this kind of code without going insane waiting for compiles to complete to find out you are off by one pixel or two. Both coordinate systems for the mouse are used in this logic (one to figure out where you are on the GUI screen and one to figure out how to tack the tooltip on the tail of the cursor.) Func show_tool_tip($pos) local $dx,$dy,$gottip,$dx,$dy,$wx,$dd,$wh_dp,$lx, $ly,$ux,$uy,$rx,$ry,$how_many_in_dp1,$wh $tpos=MouseGetPos() ;first figure out which screen we are in $dx=mod(int($pos[0]/$MWIDTH),3) $dy=mod(int($pos[1]/$MHIGH),3) $wh=$dx+$dy*3-1 if($wh>=0 AND WinActive($main_form)) Then ; check ise info ; check mrc info ; check bat info ; check ps info ; check dp info ; check dashboard and explain ; check volumes/hosts if $pos[0]>2+$dx*$MWIDTH AND $pos[0]<$dx*$MWIDTH+$MWIDTH-2 AND $pos[1]<$dy*$MHIGH+$MHIGH-104 AND $pos[1]>$dy*$MHIGH+$MHIGH-120 Then if $host_or_vol[$wh]=$DO_HOSTS Then $idx=$numhosts[$wh] Else $idx=$numvol[$wh] Endif $wx=5 for $dd=0 to $idx-1 $ttx=$dx*$MWIDTH+((int($dd/3))*$wx)+10 $tty=$dy*$MHIGH+$MHIGH119+$wx*(mod($dd,3)) if $pos[0]>=$ttx AND $pos[0]<$ttx+5 AND $pos[1]>=$tty AND $pos[1]<$tty+5 Then if($host_or_vol[$wh]=$DO_HOSTS) THen $msg=" Host "&$dd+1&" ("&$host_name[$wh][$dd]&") via WWN: "&$host_wwn[$wh][$dd]&@CRLF& _ @CRLF&" Performance is "&$host_iops[$wh][$dd]&" IOPS at "&$host_kbps[$wh][$dd]&" KB/s ("&int($host_avgxfrsize[$wh][$dd]/1024)&" KB/IO)"&@CRLF& _ " with Qdepth of "&$host_qd[$wh][$dd]&" and read/write latency of "&$host_readlat[$wh][$dd]&"/"&$host_writela t[$wh][$dd]&" ms." $msg2="HOSTINFO_" $msg3="Host HBAs" $msg4="volumes" Else $msg=" Volume "&$dd+1&" ("&$vol_name[$wh][$dd]&")"&@CRLF& _ @CRLF&" Performance is "&$vol_iops[$wh][$dd]&" IOPS at "&$vol_kbps[$wh][$dd]&" KB/s ("&int($vol_avgxfrsize[$wh][$dd]/1024)&" KB/IO)"&@CRLF& _ " with Qdepth of "&$vol_qd[$wh][$dd]&" and read/write latency of "&$vol_readlat[$wh][$dd]&"/"&$vol_writelat[ $wh][$dd]&" ms." $msg2="VOLINFO_" $msg3="volumes" $msg4="Host HBAs" EndIf If _IsPressed("02",$dll) Then $host_or_vol[$wh]=1$host_or_vol[$wh] ToolTip("Refreshing Data. Please wait",$tpos[0]+10,$tpos[1]+20,"",0,4) draw_ise_windows($REFRESH) endif If(_IsPressed("01",$dll) AND (2000<TimerDiff($begin) OR ($dd+1)<>$lastdd)) Then $begin=TimerInit() $lastdd=$dd+1 if(fileexists($msg2&$ise_ips[$wh+1]&"_"&$dd +1&".txt")) Then FileDelete($msg2&$ise_ips[$wh+1]&"_"&$dd+1& ".txt") Endif FileWrite($msg2&$ise_ips[$wh+1]&"_"&$dd+1&" .txt",$msg) Run("notepad.exe "&$msg2&$ise_ips[$wh+1]&"_"&$dd+1&".txt",@S criptDir) Else $explain=@CRLF&@CRLF&"These little dots represent "&$msg3&" with the color"&@CRLF&"going from dark (idle) to light (busy)"&@CRLF&@CRLF&"To see "&$msg4&" press right button now" ToolTip($msg&$explain,$tpos[0]+10,$tpos[1]+ 20,default,0,4) EndIf return EndIf Next EndIf ; check pdisks $wx=20 $how_many_in_dp1=0 for $dd=0 to $numdrives[$wh]-1 if($d_dp[$wh][$dd]==2 AND $how_many_in_dp1==0) Then $how_many_in_dp1=$dd $wh_dp=$d_dp[$wh][$dd]-1 $rx=mod($d_position[$wh][$dd]1,10) $ry=int((($d_position[$wh][$dd]$how_many_in_dp1)-1)/10) $lx=$dx*$MWIDTH+$wh_dp*($MWIDTH/2)+($rx*$wx )+10 $ux=$lx+13 $uy=16+$dy*$MHIGH+110+39*$ry $ly=$uy-38 if($pos[0]>$lx AND $pos[0]<$ux AND $pos[1]>$ly AND $pos[1]<$uy) Then if($d_rc[$wh][$dd]==0) Then $rcmsg="(full capacity.)" Else $rcmsg="(reduced capacity.)" Endif if($d_iops[$wh][$dd]==0) Then $avgxfer=0 Else $avgxfer=int($d_kbps[$wh][$dd]/$d_iops[$wh] [$dd]) EndIf if($d_detail[$wh][$dd]=="None") Then $showdetail="" Else $showdetail="("&$d_detail[$wh][$dd]&")" endif $msg=" Spot "&$dd+1&" (SN "&$d_sn[$wh][$dd]&") is "&$d_sts[$wh][$dd]&$showdetail&@CRLF& _ @CRLF&" It is a "&StringStripWS($d_prodid[$wh][$dd],3)&" (rev "&$d_fwver[$wh][$dd]&"), "&$d_capacity[$wh][$dd]&"GB Disk "&$rcmsg&@CRLF& _ @CRLF&" Temperature is "&int((($d_temp[$wh][$dd]*9)/5)+32)&" dF, voltages are "&StringFormat("%.2f",$d_5v[$wh][$dd]/1000) &" and "&StringFormat("%.2f",$d_12v[$wh][$dd]/1000 )&" V."&@CRLF& _ @CRLF&" Performance is "&$d_iops[$wh][$dd]&" IOPS at "&$d_kbps[$wh][$dd]&" KB/s ("&$avgxfer&"KB/IO)"&@CRLF& _ " with Qdepth of "&$d_qd[$wh][$dd]&" and read/write latency of "&$d_readlat[$wh][$dd]&"/"&$d_writelat[$wh] [$dd]&" ms." ; apologies for the following If statement. 01=left button, Timerdiff lets us debounce, ; and lastdd lets us catch different spot within debounce interval If(_IsPressed("01",$dll) AND (2000<TimerDiff($begin) OR ($dd+1)<>$lastdd)) Then $begin=TimerInit() $lastdd=$dd+1 if(fileexists("PDINFO_"&$ise_ips[$wh+1]&"_" &$dd+1&".txt")) Then FileDelete("PDINFO_"&$ise_ips[$wh+1]&"_"&$d d+1&".txt") Endif FileWrite("PDINFO_"&$ise_ips[$wh+1]&"_"&$dd +1&".txt",$msg) Run("notepad.exe PDINFO_"&$ise_ips[$wh+1]&"_"&$dd+1&".txt",@ ScriptDir) Else ToolTip($msg,$tpos[0]+10,$tpos[1]+20,defaul t,0,4) Endif return EndIf Next Endif ToolTip("") EndFunc Func draw_cheat_sheet() ; Draw Legend $leg=GuiCtrlCreateGraphic(1,1,$MWIDTH,$MHIG H) set_context($leg) GuiCtrlCreateLabel("LEGEND",275,15,120,18) GUICtrlCreateLabel("OK",232,40,20,18) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x000000,0xa0f0a0) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, 215,43,13,8) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0a0a0,$GUI_GR_NOBKCOLOR) GUICtrlCreateLabel("ReducedCap",274,40,85,1 8) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x000000,0xf0f0a0) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, 257,43,13,8) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0a0a0,$GUI_GR_NOBKCOLOR) GUICtrlCreateLabel("BAD",379,40,30,18) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x000000,0xf0a0a0) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, 362,43,13,8) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0a0a0,$GUI_GR_NOBKCOLOR) GUICtrlCreateLabel("Idle",232,80,30,18) draw_disk(215,90,0xa0f0a0,0x7a7a7a) ; idle = dark GUICtrlCreateLabel("high io",292,80,50,18) draw_disk(275,90,0xa0f0a0,0x8080fa) ; high IO = blue GUICtrlCreateLabel("high kb",358,80,55,18) draw_disk(340,90,0xa0f0a0,0x80fa80) ; high KBPS = green GUICtrlCreateLabel("high qd+latency",232,120,105,18) draw_disk(215,130,0xa0f0a0,0xfa80fa) ; high QD+RLAT+WLAT = red GUICtrlCreateLabel("Busy!",358,120,40,18) draw_disk(340,130,0xa0f0a0,0xffffff) ; Real Busy = whitish GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x000000,$GUI_GR_NOBKCOLOR) draw_line(215,145,220,145) draw_line(215,148,222,148) draw_line(215,151,225,151) GUICtrlCreateLabel("qd+lat over iops over kbps",235,140,170,20) GUICtrlCreateLabel("Mouse around for more info",220,200,190,20) GUICtrlCreateLabel("ISE",240,170,30,18) GUICtrlCreateLabel("MRC1",300,170,40,18) GUICtrlCreateLabel("MRC2",370,170,40,18) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0, 0xc060c0) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 235,182,20,180,-40) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc0a050, 0xc0a050) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 295,182,20,180,-40) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0c060, 0xa0c060) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 365,182,20,180,-40) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0,$GUI_GR_NOBKCOLOR) EndFunc Func draw_line($sx,$sy,$tx,$ty) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, $sx, $sy) ; start point GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, $tx, $ty) EndFunc Func draw_led($sts,$xx,$yy) $retc=set_warning_color($sts) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x000000,$retc) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, $xx, $yy,13,13) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0a0a0,$GUI_GR_NOBKCOLOR) GuiCtrlSetDefColor(0x000000) EndFunc Func draw_filled($sx,$sy,$dx,$dy,$clr) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, $clr,$clr) GUICtrlSetGraphic($cwnd, $GUI_GR_RECT, $sx,$sy,$dx,$dy) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0a0a0,$GUI_GR_NOBKCOLOR) GuiCtrlSetDefColor(0x000000) EndFunc This logic seems to be the favorite of the storage geeks (along with pegging the IOPS and KBPS meters). Keep in mind that busy is good as long as busy doesn’t mean excessive latency at the server level. Virtualized storage tends to run full tilt whenever possible so that more bandwidth and lower latency is available when it is needed (i.e. speed is good.) Func draw_drives($wh) $wx=20 $how_many_in_dp1=0 for $dd=0 to $numdrives[$wh]-1 if($d_dp[$wh][$dd]==2 AND $how_many_in_dp1==0) Then $how_many_in_dp1=$dd if($d_sts[$wh][$dd]=="Operational") Then $rc=0xa0f0a0 ;green (OK) if($d_rc[$wh][$dd]<>0) then $rc=0xf0f0a0 ;yellow (warning) Else $rc=0xf0a0a0 EndIf $ti=$d_iops[$wh][$dd] if($ti>500) then $ti=500 $ti=int($ti*128/500) $tk=$d_kbps[$wh][$dd] if($tk>30000) then $tk=30000 $tk=int($tk*128/30000) $tq=$d_qd[$wh][$dd]+$d_readlat[$wh][$dd]/2+ $d_writelat[$wh][$dd]/2 if($tq>100) then $tq=100 $tq=int($tq*128/100) $bc=0x7a7a7a+int($tq)*0x010000+int($tk)*0x0 100+int($ti)*0x01 $wh_dp=$d_dp[$wh][$dd]-1 $rx=mod($d_position[$wh][$dd]-1,10) $ry=int((($d_position[$wh][$dd]$how_many_in_dp1)-1)/10) draw_disk($wh_dp*($MWIDTH/2)+($rx*$wx)+10,1 10+39*$ry,$rc,$bc) $tq=$tq*13/128 $ti=$ti*13/128 $tk=$tk*13/128 $ttx=$wh_dp*($MWIDTH/2)+($rx*$wx)+10 $tty=110+39*$ry+8 GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x000000,$GUI_GR_NOBKCOLOR) draw_line($ttx,$tty,$ttx+int($tq),$tty) draw_line($ttx,$tty+3,$ttx+int($ti),$tty+3) draw_line($ttx,$tty+6,$ttx+int($tk),$tty+6) next EndFunc The following is the late addition to the display. Graphically it doesn’t feel right yet but it works and gives you a wealth of info that you don’t normally want to have to burrow down for in subwindows. This will make more sense if you have one server that is really busy. Func draw_hosts_or_vols($wh) $wx=5 $choice=$host_or_vol[$wh] if($choice=$DO_HOSTS) Then $idx=$numhosts[$wh] Else $idx=$numvol[$wh] Endif GUICtrlSetGraphic($aa[$wh], $GUI_GR_COLOR, 0xf0f0f0, 0xf0f0f0) GUICtrlSetGraphic($aa[$wh], $GUI_GR_RECT, 3,$MHIGH-119,$MWIDTH-6,15) for $dd=0 to $idx-1 If($choice=$DO_HOSTS) Then $ti=$host_iops[$wh][$dd] $tk=$host_kbps[$wh][$dd] $tq=$host_qd[$wh][$dd]+$host_readlat[$wh][$ dd]/2+$host_writelat[$wh][$dd]/2 Else $ti=$vol_iops[$wh][$dd] $tk=$vol_kbps[$wh][$dd] $tq=$vol_qd[$wh][$dd]+$vol_readlat[$wh][$dd ]/2+$vol_writelat[$wh][$dd]/2 Endif if($ti>5000) then $ti=5000 $ti=int($ti*128/5000) if($tk>30000) then $tk=30000 $tk=int($tk*128/30000) if($tq>100) then $tq=100 $tq=int($tq*128/100) $bc=0x7a7a7a+int($tq)*0x010000+int($tk)*0x0 100+int($ti)*0x01 $ttx=((int($dd/3))*$wx)+10 $tty=$MHIGH-119+$wx*(mod($dd,3)) GUICtrlSetGraphic($aa[$wh], $GUI_GR_COLOR, $bc,$GUI_GR_NOBKCOLOR) $tcw=$cwnd $cwnd=$aa[$wh] draw_line($ttx,$tty,$ttx+3,$tty) draw_line($ttx,$tty+1,$ttx+3,$tty+1) draw_line($ttx,$tty+2,$ttx+3,$tty+2) draw_line($ttx,$tty+3,$ttx+3,$tty+3) $cwnd=$tcw GUICtrlSetGraphic($aa[$wh], $GUI_GR_COLOR, 0x000000,$GUI_GR_NOBKCOLOR) next EndFunc This is the dashboard logic. Basically brute force coding, with some trips down memory lane remembering how to intersect an arc with a line…and then properly rotating the coordinate system. Func drawcat($dx,$dy,$ise_iops,$cn1_iops,$cn2_io ps,$ise_kbps,$cn1_kbps,$cn2_kbps,$cn1_qd,$c n2_qd,$cn1_readlat,$cn2_readlat,$cn1_writel at,$cn2_writelat) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x505050,$GUI_GR_NOBKCOLOR) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, 8,$MHIGH-96,30,30) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 95,$MHIGH-23,70,90,90) GUICtrlSetGraphic($cwnd, $GUI_GR_RECT, 100,$MHIGH-93,17,70) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 120,$MHIGH-23,70,0,90) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE,180,$MHIGH-96,30,30) ; now calculate the eye size for qdepths (full size eye for qdepth>=30) $t=$cn2_qd if($t>$MAXQD) then $t=$MAXQD $t=int(($t*29/$MAXQD)+.5) if($t>0) Then $rc=0x909090 if($t>5) then $rc=0xa0a0b0 if($t>10) then $rc=0xe0e070 if($t>20) then $rc=0xe08080 GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, $rc,$rc) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, 180+15-($t+1)/2,$MHIGH96+15-($t+1)/2,$t,$t) EndIf $t=$cn1_qd if($t>$MAXQD) then $t=$MAXQD $t=int(($t*29/$MAXQD)+.5) if($t>0) Then $rc=0x909090 if($t>5) then $rc=0xa0a0b0 if($t>10) then $rc=0xe0e080 if($t>20) then $rc=0xe08080 GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, $rc,$rc) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, 8+15-($t+1)/2,$MHIGH96+15-($t+1)/2,$t,$t) EndIf ; now for the tach (IOPS) GUICtrlSetGraphic($cwnd,$GUI_GR_PENSIZE,2) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0,$GUI_GR_NOBKCOLOR) $t=$ise_iops if($t>$MAXIOPS) then $t=$MAXIOPS $t=90-int($t*90/$MAXIOPS) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, 95,$MHIGH-23) GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, 95(76*(sin((($t*3.14159265358979))/180))),$MH IGH-23(75*(cos((($t*3.14159265358979)/180))))) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc0a050,$GUI_GR_NOBKCOLOR) $t1=$cn1_iops if($t1>$MAXIOPS) then $t1=$MAXIOPS $t1=90-int($t1*90/$MAXIOPS) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, 95,$MHIGH-23) GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, 95(74*(sin((($t1*3.14159265358979))/180))),$M HIGH-23(75*(cos((($t1*3.14159265358979)/180))))) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0c060,$GUI_GR_NOBKCOLOR) $t2=$cn2_iops if($t2>$MAXIOPS) then $t2=$MAXIOPS $t2=90-int($t2*90/$MAXIOPS) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, 95,$MHIGH-23) GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, 95(72*(sin((($t2*3.14159265358979))/180))),$M HIGH-23(75*(cos((($t2*3.14159265358979)/180))))) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0, 0xc060c0) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 95,$MHIGH-23,60,180,-(90-$t)) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc0a050, 0xc0a050) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 95,$MHIGH-23,50,180,-(90-$t1)) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0c060, 0xa0c060) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 95,$MHIGH-23,40,180,-(90-$t2)) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0,$GUI_GR_NOBKCOLOR) ; now for the speed (KBPS) $t=$ise_kbps if($t>$MAXKBPS) then $t=$MAXKBPS $t=90-int($t*90/$MAXKBPS) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, 120,$MHIGH-23) GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, 120+(76*(sin((($t*3.14159265358979))/180))) ,$MHIGH-23(75*(cos((($t*3.14159265358979)/180))))) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc0a050,$GUI_GR_NOBKCOLOR) $t1=$cn1_kbps if($t1>$MAXKBPS) then $t1=$MAXKBPS $t1=90-int($t1*90/$MAXKBPS) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, 120,$MHIGH-23) GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, 120+(74*(sin((($t1*3.14159265358979))/180)) ),$MHIGH-23(75*(cos((($t1*3.14159265358979)/180))))) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0c060,$GUI_GR_NOBKCOLOR) $t2=$cn2_kbps if($t2>$MAXKBPS) then $t2=$MAXKBPS $t2=90-int($t2*90/$MAXKBPS) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, 120,$MHIGH-23) GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, 120+(72*(sin((($t2*3.14159265358979))/180)) ),$MHIGH-23(75*(cos((($t2*3.14159265358979)/180))))) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0, 0xc060c0) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 120,$MHIGH-23,60,0,(90-$t)) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc0a050, 0xc0a050) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 120,$MHIGH-23,50,0,(90-$t1)) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0c060, 0xa0c060) GUICtrlSetGraphic($cwnd, $GUI_GR_PIE, 120,$MHIGH-23,40,0,(90-$t2)) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0,$GUI_GR_NOBKCOLOR) ; now for the gear (io size) if($ise_iops==0) Then $t=0 Else $t=$ise_kbps/$ise_iops EndIf if($t>$MAXIOSZ) then $t=$MAXIOSZ $t=70-int($t*70/$MAXIOSZ) GUICtrlSetGraphic($cwnd, $GUI_GR_MOVE, 97, $MHIGH-93+$t) GUICtrlSetGraphic($cwnd, $GUI_GR_LINE, 118, $MHIGH-93+$t) GUICtrlSetGraphic($cwnd,$GUI_GR_PENSIZE,1) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xc060c0,0xc060c0) GUICtrlSetGraphic($cwnd, $GUI_GR_RECT, 101,$MHIGH-93+$t,15,70-$t) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0a0a0,$GUI_GR_NOBKCOLOR) EndFunc Func set_context($wnd) $cwnd=$wnd EndFunc Func draw_disk($x,$y,$topc,$bodyc) ; normalize the rgb values down by 3 bits per color...this reduces the number of GDI Objects ; used by the system by a factor of 8x8x8. NOTE: drawing EVERY color will eventually use up all memory $redc=int($bodyc/0x10000) $greenc=mod(int($bodyc/0x100),0x100) $bluec=mod($bodyc,0x100) $redc=int($redc/8)*8 $greenc=int($greenc/8)*8 $bluec=int($bluec/8)*8 $bodyc=$bluec+($greenc*0x100)+($redc*0x1000 0) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, $bodyc,$bodyc) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, $x,$y-2,13,8) GUICtrlSetGraphic($cwnd, $GUI_GR_RECT, $x,$y-16,13,18) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0x000000,$topc) GUICtrlSetGraphic($cwnd, $GUI_GR_ELLIPSE, $x,$y-18,13,8) GUICtrlSetGraphic($cwnd, $GUI_GR_COLOR, 0xa0a0a0,$GUI_GR_NOBKCOLOR) Endfunc And this is the paint logic for all the ISE sub windows. Just brute force logic that works off of data variables in memory at the time. Func draw_ise_windows($how) $dy=0 $dx=1 ;beep(500,150) GUISetState(@SW_LOCK,$main_form) for $i = 0 to 7 $L_NUM_BAD=0 $L_NUM_WARN=0 $need_erase=0 if($how=$REFRESH) Then GuiCtrlDelete($aa[$i]) Else GUICtrlCreateLabel("MRC1", 20+$MWIDTH*$dx, 32+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("MRC2", 20+$MWIDTH/2+$MWIDTH*$dx, 32+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("DP1", 20+$MWIDTH*$dx, 68+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("DP2", 20+$MWIDTH/2+$MWIDTH*$dx, 68+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("BAT1", 20+$MWIDTH*$dx, 50+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("BAT2", 120+$MWIDTH*$dx, 50+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("PS1", 20+$MWIDTH/2+$MWIDTH*$dx, 50+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("PS2", 120+$MWIDTH/2+$MWIDTH*$dx, 50+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("Q1", 5+$MWIDTH*$dx, $MHIGH-21+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("IOPS",45+$MWIDTH*$dx, $MHIGH-21+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("SZ", 100+$MWIDTH*$dx, $MHIGH-21+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("KBPS",140+$MWIDTH*$dx, $MHIGH-21+$MHIGH*$dy, 50,16) GUICtrlCreateLabel("Q2",190+$MWIDTH*$dx, $MHIGH-21+$MHIGH*$dy, 30,16) EndIf $aa[$i]=GuiCtrlCreateGraphic($MWIDTH*$dx,$M HIGH*$dy,$MWIDTH,$MHIGH) set_context($aa[$i]) if($i<UBound($ise_ips)-1) Then if(process_xmls($ise_ips[$i+1],$i)=1) Then GUICtrlSetDefColor(0x000000) GUICtrlSetBkColor($aa[$i], $GUI_BKCOLOR_TRANSPARENT) draw_line(16+$MWIDTH/2,$MHIGH104,16+$MWIDTH/2,$MHIGH-4) draw_line(2,$MHIGH-120,$MWIDTH2,$MHIGH-120) draw_line(16+$MWIDTH/2,$MHIGH84,$MWIDTH-3,$MHIGH-84) draw_line(16+$MWIDTH/2,$MHIGH64,$MWIDTH-3,$MHIGH-64) draw_line(16+$MWIDTH/2,$MHIGH44,$MWIDTH-3,$MHIGH-44) draw_line(16+$MWIDTH/2,$MHIGH24,$MWIDTH-3,$MHIGH-24) If($how==$INIT) Then $G_QD_L[$i]= GuiCtrlCreateLabel("QD",20+$MWIDTH/2+$MWIDT H*$dx,$MHIGH-101+$MHIGH*$dy,40,16) $G_IO_L[$i]= GuiCtrlCreateLabel("IO/s",20+$MWIDTH/2+$MWI DTH*$dx,$MHIGH-81+$MHIGH*$dy,40,16) $G_KB_L[$i]= GuiCtrlCreateLabel("KB/s",20+$MWIDTH/2+$MWI DTH*$dx,$MHIGH-61+$MHIGH*$dy,40,16) $G_RWPCT_L[$i]= GuiCtrlCreateLabel("RD%",20+$MWIDTH/2+$MWID TH*$dx,$MHIGH-41+$MHIGH*$dy,40,16) $G_MXLAT_L[$i]= GuiCtrlCreateLabel("MaxL",20+$MWIDTH/2+$MWI DTH*$dx,$MHIGH-21+$MHIGH*$dy,40,16) GUICtrlSetDefColor(0x801080) $G_QD_I[$i]= GuiCtrlCreateLabel($ise_qd,40+20+$MWIDTH/2+ $MWIDTH*$dx,$MHIGH-101+$MHIGH*$dy,48,16) $G_IO_I[$i]= GuiCtrlCreateLabel($ise_iops,40+20+$MWIDTH/ 2+$MWIDTH*$dx,$MHIGH-81+$MHIGH*$dy,48,16) $G_KB_I[$i]= GuiCtrlCreateLabel($ise_kbps,40+20+$MWIDTH/ 2+$MWIDTH*$dx,$MHIGH-61+$MHIGH*$dy,48,16) $G_RWPCT_I[$i]= GuiCtrlCreateLabel($ise_readpct,40+20+$MWID TH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,48,16) $G_MXLAT_I[$i]= GuiCtrlCreateLabel(_Max(Number($ise_readlat ),Number($ise_writelat)),40+20+$MWIDTH/2+$M WIDTH*$dx,$MHIGH-21+$MHIGH*$dy,48,16) GUICtrlSetDefColor(0x807010) $G_QD_1[$i]= GuiCtrlCreateLabel($cn1_qd,88+20+$MWIDTH/2+ $MWIDTH*$dx,$MHIGH-101+$MHIGH*$dy,47,16) $G_IO_1[$i]= GuiCtrlCreateLabel($cn1_iops,88+20+$MWIDTH/ 2+$MWIDTH*$dx,$MHIGH-81+$MHIGH*$dy,47,16) $G_KB_1[$i]= GuiCtrlCreateLabel($cn1_kbps,88+20+$MWIDTH/ 2+$MWIDTH*$dx,$MHIGH-61+$MHIGH*$dy,47,16) $G_RWPCT_1[$i]= GuiCtrlCreateLabel($cn1_readpct,88+20+$MWID TH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,47,16) $G_MXLAT_1[$i]= GuiCtrlCreateLabel(_Max(Number($cn1_readlat ),Number($cn1_writelat)),88+20+$MWIDTH/2+$M WIDTH*$dx,$MHIGH-21+$MHIGH*$dy,47,16) GUICtrlSetDefColor(0x507010) $G_QD_2[$i]= GuiCtrlCreateLabel($cn2_qd,135+20+$MWIDTH/2 +$MWIDTH*$dx,$MHIGH-101+$MHIGH*$dy,45,16) $G_IO_2[$i]= GuiCtrlCreateLabel($cn2_iops,135+20+$MWIDTH /2+$MWIDTH*$dx,$MHIGH-81+$MHIGH*$dy,45,16) $G_KB_2[$i]= GuiCtrlCreateLabel($cn2_kbps,135+20+$MWIDTH /2+$MWIDTH*$dx,$MHIGH-61+$MHIGH*$dy,45,16) $G_RWPCT_2[$i]= GuiCtrlCreateLabel($cn2_readpct,135+20+$MWI DTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,45,16) $G_MXLAT_2[$i]= GuiCtrlCreateLabel(_Max(Number($cn2_readlat ),Number($cn2_writelat)),135+20+$MWIDTH/2+$ MWIDTH*$dx,$MHIGH-21+$MHIGH*$dy,43,16) GUICtrlSetDefColor(0x000000) $G_TOP[$i]=GUICtrlCreateLabel("ISE (SN="&$ise_sn&") IP(s)="&$cn1_ip&"/"&$cn2_ip, 20+$MWIDTH*$dx, 8+$MHIGH*$dy, $MWIDTH-70, 16) $G_CN1[$i]=GUICtrlCreateLabel("(FW="&$cn1_f wver&")", 60+$MWIDTH*$dx, 32+$MHIGH*$dy, $MWIDTH/2-100,16) $G_CN2[$i]=GUICtrlCreateLabel("(FW="&$cn2_f wver&")", 60+$MWIDTH/2+$MWIDTH*$dx, 32+$MHIGH*$dy, $MWIDTH/2-100,16) $G_DP1[$i]=GUICtrlCreateLabel("(FW="&$dp1_f wver&")", 60+$MWIDTH*$dx, 68+$MHIGH*$dy, $MWIDTH/2-80,16) $G_DP2[$i]=GUICtrlCreateLabel("(FW="&$dp2_f wver&")", 60+$MWIDTH/2+$MWIDTH*$dx, 68+$MHIGH*$dy, $MWIDTH/2-80,16) Else GuiCtrlSetData($G_QD_L[$i],"QD") GUICtrlSetData($G_IO_L[$i], "IO/s") GUICtrlSetData($G_KB_L[$i], "KB/s") GUICtrlSetData($G_RWPCT_L[$i], "RD%") GUICtrlSetData($G_MXLAT_L[$i], "MaxL") GUICtrlSetDefColor(0x801080) GuiCtrlSetData($G_QD_I[$i], $ise_qd) GUICtrlSetData($G_IO_I[$i], $ise_iops) GUICtrlSetData($G_KB_I[$i], $ise_kbps) GUICtrlSetData($G_RWPCT_I[$i], $ise_readpct) GUICtrlSetData($G_MXLAT_I[$i], _Max(Number($ise_readlat),Number($ise_write lat))) GUICtrlSetDefColor(0x807010) GUICtrlSetData($G_QD_1[$i], $cn1_qd) GUICtrlSetData($G_IO_1[$i], $cn1_iops) GUICtrlSetData($G_KB_1[$i], $cn1_kbps) GUICtrlSetData($G_RWPCT_1[$i], $cn1_readpct) GUICtrlSetData($G_MXLAT_1[$i], _Max(Number($cn1_readlat),Number($cn1_write lat))) GUICtrlSetDefColor(0x507010) GUICtrlSetData($G_QD_2[$i], $cn2_qd) GUICtrlSetData($G_IO_2[$i], $cn2_iops) GUICtrlSetData($G_KB_2[$i], $cn2_kbps) GUICtrlSetData($G_RWPCT_2[$i], $cn2_readpct) GUICtrlSetData($G_MXLAT_2[$i], _Max(Number($cn2_readlat),Number($cn2_write lat))) GUICtrlSetDefColor(0x000000) GUICtrlSetData($G_TOP[$i],"ISE (SN="&$ise_sn&") IP(s)="&$cn1_ip&"/"&$cn2_ip) GUICtrlSetData($G_CN1[$i],"(FW="&$cn1_fwver &")") GUICtrlSetData($G_CN2[$i],"(FW="&$cn2_fwver &")") GUICtrlSetData($G_DP1[$i],"(FW="&$dp1_fwver &")") GUICtrlSetData($G_DP2[$i],"(FW="&$dp2_fwver &")") EndIf draw_led($ise_sts,3,10) draw_led($cn1_sts, 3,33) draw_led($cn2_sts, $MWIDTH/2+3,33) draw_led($dp1_sts, 3,69) draw_led($dp2_sts, $MWIDTH/2+3,69) draw_led($bat1_sts, 3,52) draw_led($ps1_sts, $MWIDTH/2+3,52) draw_led($bat2_sts, $MWIDTH/4+3,52) draw_led($ps2_sts, $MWIDTH/2+$MWIDTH/4+3,52) draw_drives($i) draw_hosts_or_vols($i) drawcat($dx,$dy,$ise_iops,$cn1_iops,$cn2_io ps,$ise_kbps,$cn1_kbps,$cn2_kbps,$cn1_qd,$c n2_qd,$cn1_readlat,$cn2_readlat,$cn1_writel at,$cn2_writelat) GUICtrlSetDefColor(0x000000) else If($how==$INIT) Then $G_TOP[$i]=GUICtrlCreateLabel("Requesting data from IP: "&$ise_ips[$i+1], 20+$MWIDTH*$dx, 8+$MHIGH*$dy, $MWIDTH-70, 16) Else GUICtrlSetData($G_TOP[$i],"Requesting data from IP: "&$ise_ips[$i+1]) EndIf $need_erase=1 $L_NUM_WARN=1 endif Else If($how==$INIT) Then $G_TOP[$i]=GUICtrlCreateLabel(" ", 20+$MWIDTH*$dx, 8+$MHIGH*$dy, $MWIDTH70, 16) Else GUICtrlSetData($G_TOP[$i]," ") EndIf $need_erase=1 EndIf if($need_erase==1) Then If($how==$INIT) Then $G_CN1[$i]=GUICtrlCreateLabel(" ", 60+$MWIDTH*$dx, 32+$MHIGH*$dy, $MWIDTH/2-85,16) $G_CN2[$i]=GUICtrlCreateLabel(" ", 70+$MWIDTH/2+$MWIDTH*$dx, 32+$MHIGH*$dy, $MWIDTH/2-85,16) $G_DP1[$i]=GUICtrlCreateLabel(" ", 60+$MWIDTH*$dx, 68+$MHIGH*$dy, $MWIDTH/2-85,16) $G_DP2[$i]=GUICtrlCreateLabel(" ", 70+$MWIDTH/2+$MWIDTH*$dx, 68+$MHIGH*$dy, $MWIDTH/2-85,16) $G_QD_L[$i]= GuiCtrlCreateLabel(" ",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,40,16) $G_IO_L[$i]= GuiCtrlCreateLabel(" ",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,40,16) $G_KB_L[$i]= GuiCtrlCreateLabel(" ",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,40,16) $G_RWPCT_L[$i]= GuiCtrlCreateLabel(" ",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,40,16) $G_MXLAT_L[$i]= GuiCtrlCreateLabel(" ",20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,40,16) GUICtrlSetDefColor(0x801080) $G_QD_I[$i]= GuiCtrlCreateLabel(" ",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,48,16) $G_IO_I[$i]= GuiCtrlCreateLabel(" ",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,48,16) $G_KB_I[$i]= GuiCtrlCreateLabel(" ",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,48,16) $G_RWPCT_I[$i]= GuiCtrlCreateLabel(" ",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,48,16) $G_MXLAT_I[$i]= GuiCtrlCreateLabel(" ",40+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,48,16) GUICtrlSetDefColor(0x807010) $G_QD_1[$i]= GuiCtrlCreateLabel(" ",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,47,16) $G_IO_1[$i]= GuiCtrlCreateLabel(" ",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,47,16) $G_KB_1[$i]= GuiCtrlCreateLabel(" ",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,47,16) $G_RWPCT_1[$i]= GuiCtrlCreateLabel(" ",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,47,16) $G_MXLAT_1[$i]= GuiCtrlCreateLabel(" ",88+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,47,16) GUICtrlSetDefColor(0x507010) $G_QD_2[$i]= GuiCtrlCreateLabel(" ",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH101+$MHIGH*$dy,45,16) $G_IO_2[$i]= GuiCtrlCreateLabel(" ",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH81+$MHIGH*$dy,45,16) $G_KB_2[$i]= GuiCtrlCreateLabel(" ",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH61+$MHIGH*$dy,45,16) $G_RWPCT_2[$i]= GuiCtrlCreateLabel(" ",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH41+$MHIGH*$dy,45,16) $G_MXLAT_2[$i]= GuiCtrlCreateLabel(" ",135+20+$MWIDTH/2+$MWIDTH*$dx,$MHIGH21+$MHIGH*$dy,43,16) GUICtrlSetDefColor(0x000000) Else GUICtrlSetData($G_CN1[$i]," ") GUICtrlSetData($G_CN2[$i]," ") GUICtrlSetData($G_DP1[$i]," ") GUICtrlSetData($G_DP2[$i]," ") GUICtrlSetData($G_QD_L[$i], " ") GUICtrlSetData($G_QD_I[$i], " ") GUICtrlSetData($G_QD_1[$i], " ") GUICtrlSetData($G_QD_2[$i], " ") GUICtrlSetData($G_IO_L[$i], " ") GUICtrlSetData($G_IO_I[$i], " ") GUICtrlSetData($G_IO_1[$i], " ") GUICtrlSetData($G_IO_2[$i], " ") GUICtrlSetData($G_KB_L[$i], " ") GUICtrlSetData($G_KB_I[$i], " ") GUICtrlSetData($G_KB_1[$i], " ") GUICtrlSetData($G_KB_2[$i], " ") GUICtrlSetData($G_RWPCT_L[$i], " ") GUICtrlSetData($G_RWPCT_I[$i], " ") GUICtrlSetData($G_RWPCT_1[$i], " ") GUICtrlSetData($G_RWPCT_2[$i], " ") GUICtrlSetData($G_MXLAT_L[$i], " ") GUICtrlSetData($G_MXLAT_I[$i], " ") GUICtrlSetData($G_MXLAT_1[$i], " ") GUICtrlSetData($G_MXLAT_2[$i], " ") EndIf draw_line(16+$MWIDTH/2,$MHIGH104,16+$MWIDTH/2,$MHIGH-4) draw_line(2,$MHIGH-120,$MWIDTH2,$MHIGH-120) draw_line(16+$MWIDTH/2,$MHIGH84,$MWIDTH-3,$MHIGH-84) draw_line(16+$MWIDTH/2,$MHIGH64,$MWIDTH-3,$MHIGH-64) draw_line(16+$MWIDTH/2,$MHIGH44,$MWIDTH-3,$MHIGH-44) draw_line(16+$MWIDTH/2,$MHIGH24,$MWIDTH-3,$MHIGH-24) endif GUICtrlSetBkColor($aa[$i], $GUI_BKCOLOR_TRANSPARENT) if($L_NUM_BAD > 0) then GUICtrlSetGraphic($aa[$i], $GUI_GR_COLOR, 0xff0000) elseif ($L_NUM_WARN >0) Then GUICtrlSetGraphic($aa[$i],$GUI_GR_COLOR,0xc 0c000) else GUICtrlSetGraphic($aa[$i], $GUI_GR_COLOR, 0x00ff00) endif GUICtrlSetGraphic($aa[$i],$GUI_GR_RECT, 0,0,$MWIDTH,$MHIGH) ;box around everything GUICtrlSetGraphic($aa[$i],$GUI_GR_RECT, 1,1,$MWIDTH-2,$MHIGH-2) ;thicken (could use pen=2) GUICtrlSetGraphic($aa[$i], $GUI_GR_COLOR, 0) ;go back to black text GUICtrlSetGraphic($aa[$i],$GUI_GR_RECT, 2,2,$MWIDTH-4,$MHIGH-4) ;and draw inner box lines draw_line(2,30,$MWIDTH-2,30) draw_line(2,49,$MWIDTH-2,49) draw_line(2,67,$MWIDTH-2,67) draw_line($MWIDTH/2+$MWIDTH/4,49,$MWIDTH/2+ $MWIDTH/4,67) draw_line($MWIDTH/4,49,$MWIDTH/4,67) draw_line(2,85,$MWIDTH-2,85) draw_line($MWIDTH/2,$MHIGH120,$MWIDTH/2,30) draw_line(2,$MHIGH-104,$MWIDTH-2,$MHIGH104) if($dx==2) then $dx=0 $dy=$dy+1 Else $dx=$dx+1 endif next GUISetState(@SW_UNLOCK,$main_form) GUISetState(@SW_SHOW) EndFunc ; ; GUI window setup followed by exit (cleanup) routine ; Func window_setup($verstr) If WinExists($verstr) <> 0 Then WinActivate($verstr) Exit EndIf $main_form = GUICreate($verstr, $MWIDTH*3, $MHIGH*3, -1, -1) $listview = GUICtrlCreateListView("#|IP ADDRESSES", 8, 8, 200, $MHIGH-35, $LVS_REPORT) GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 30) GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 390) GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 144) $add_input = GUICtrlCreateInput("", 8, $MHIGH-25, 180, 21) $add_button = GUICtrlCreateButton("Add", 210, $MHIGH-25, 46, 25, BitOR($BS_DEFPUSHBUTTON,$WS_GROUP)) $sample_button = GUICtrlCreateButton("Sample=2s", 326, $MHIGH-25, 85, 25, $WS_GROUP) $delete_button = GUICtrlCreateButton("Delete", 260, $MHIGH25, 59, 25, $WS_GROUP) $agecaps_button = GUICtrlCreateButton("Age captures", 210, $MHIGH-55, 95, 25, $WS_GROUP) $stopstartcaps_button = GUICtrlCreateButton("Start captures", 311, $MHIGH-55, 100, 25, $WS_GROUP) EndFunc Func gui_exit() _GUICtrlListView_UnRegisterSortCallBack($li stview) DllClose($dll) GUIDelete() EndFunc ; ; following logic just takes a status string and figures out a warning color based on text in the String ; Func set_warning_color($msg) if((StringInStr($msg,"Crit",0)>0) OR (StringInStr($msg,"Bad",0)>0) OR (StringInStr($msg,"FAIL",0)>0) OR (StringInstr($msg,"[F",0)>0) OR (StringInStr($msg,"Non",0)>0)) Then $retcolor=0xa00000 elseif((StringInStr($msg,"[W",0) >0) OR (StringInStr($msg,"degrad",0)>0) OR (StringInStr($msg,"risk",0)>0) OR (StringInStr($msg,"Warning",0)>0)) Then $retcolor=0xb0b000 Else $retcolor=0x00a000 EndIf GuiCtrlSetDefColor($retcolor) return $retcolor EndFunc ; ; following logic configures and handles the listview box (used to select IP addresses) ; Func setup_listview() $hListView = GUICtrlGetHandle($listview) GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY') GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") GUISetState() GUICtrlSetData($listview, "#|IP ADDRESSES ("&$ip_cnt&")") If $ip_cnt > 0 Then For $i=1 To $ip_cnt GUICtrlCreateListViewItem($i & "|" & $ise_ips[$i], $listview) Next _GUICtrlListView_EnsureVisible($hListView, $ip_cnt) EndIf _WinAPI_RedrawWindow($hListView) _GUICtrlListView_RegisterSortCallBack($hLis tView) _GUICtrlListView_SortItems($hListView, 1) EndFunc Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg, $iwParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo $hWndListView = $hListView If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView) $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $hWndListView Switch $iCode Case $LVN_COLUMNCLICK ; A column was clicked $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam) _GUICtrlListView_SortItems($hWndFrom, DllStructGetData($tInfo, "SubItem")) Case $NM_DBLCLK ; Sent by a list-view control when the user doubleclicks an item with the left mouse button Local $aRect Local $aHit = _GUICtrlListView_SubItemHitTest($hListView) If ($aHit[0] <> -1) And ($aHit[1] = 0) Then $Item = $aHit[0] $SubItem = 0 $aRect = _GUICtrlListView_GetItemRect($hListView, $Item) ElseIf ($aHit[0] <> -1) And ($aHit[1] > 0) Then $Item = $aHit[0] $SubItem = $aHit[1] $aRect = _GUICtrlListView_GetSubItemRect($hListView, $Item, $SubItem) Else Return $GUI_RUNDEFMSG EndIf Local $iItemText = _GUICtrlListView_GetItemText($hListView, $Item, $SubItem) If $SubItem = 1 Then Local $iLen = 377 Else Local $iLen = 131 EndIf Local $aPos = ControlGetPos($main_form, "", $hListView) Local $iX = $aPos[0] + $aRect[0] + 5 Local $iY = $aPos[1] + $aRect[1] + 2 Global $hEdit = _GUICtrlEdit_Create($main_form, $iItemText, $iX, $iY, $iLen + 10, 17, $Style) _GUICtrlEdit_SetSel($hEdit, 0, -1) _WinAPI_SetFocus($hEdit) $hDC = _WinAPI_GetWindowDC($hEdit) $hBrush = _WinAPI_CreateSolidBrush(0x000000) FrameRect($hDC, 0, 0, $iLen + 10, 17, $hBrush) Case $NM_RCLICK Case $LVN_HOTTRACK ;future tooltip implementation EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func RGB2BGR($iColor) Return BitAND(BitShift(String(Binary($iColor)), 8), 0xFFFFFF) EndFunc ;==>RGB2BGR Func FrameRect($hDC, $nLeft, $nTop, $nRight, $nBottom, $hBrush) Local $stRect = DllStructCreate("int;int;int;int") DllStructSetData($stRect, 1, $nLeft) DllStructSetData($stRect, 2, $nTop) DllStructSetData($stRect, 3, $nRight) DllStructSetData($stRect, 4, $nBottom) DllCall("user32.dll", "int", "FrameRect", "hwnd", $hDC, "ptr", DllStructGetPtr($stRect), "hwnd", $hBrush) EndFunc ;==>FrameRect Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam) #forceref $hWnd, $Msg Local $hWndFrom, $iIDFrom, $hWndEdit, $iCode ; Local $iCode = BitShift($wParam, 16) If Not IsHWnd($hEdit) Then $hWndEdit = GUICtrlGetHandle($hEdit) $hWndFrom = $lParam $iIDFrom = _WinAPI_LoWord($wParam) $iCode = _WinAPI_HiWord($wParam) If _IsPressed("0D", $dll) Then GUICtrlSetState($add_input, $GUI_FOCUS) EndIf Switch $lParam Case $hEdit, $hWndEdit Switch $iCode Case $EN_KILLFOCUS Local $iText = _GUICtrlEdit_GetText($hEdit) _GUICtrlListView_SetItemText($hListView, $Item, $iText, $SubItem) _WinAPI_DeleteObject($hBrush) _WinAPI_ReleaseDC($hEdit, $hDC) _WinAPI_DestroyWindow($hEdit) $Item = -1 $SubItem = 0 EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND And that is it. When first coded up there was a fear by the developer that this might be a bit frail, so extra logic was put in to ensure that it wasn’t impacted if capitalization of XML tags changed (they did) or path logic changed (it did a bit). Actually pretty much all search logic is set to default to case insensitive, which allows you to get a little sloppy with the coding as well with no impact. At the time of this writing the current logic works with the earliest Restful alpha code that I had access to as well as the most recent code. No promises that something down the line won’t break it but should be easy to fix. AUTOIT: NOTE: while stat5000.exe is compiled using AutoIt, it is not necessary to install the autoit compiler on your workstation to actually use stat5000 unless you intend to modify the code in some form or another. If you do want to modify the code then autoit is a free download that takes just minutes to install and is trivial to use. As the following sections mention, it is a ‘basic-like’ language, but in actuality it is also a ‘C’ like language and even in some cases a C++ like language. After programming in them all they tend to blend together anyway. The following is right from the autoit home page (http://www.autoitscript.com/autoit3/): AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying "runtimes" required! AutoIt was initially designed for PC "roll out" situations to reliably automate and configure thousands of PCs. Over time it has become a powerful language that supports complex expressions, user functions, loops and everything else that veteran scripters would expect. Features: Easy to learn BASIC-like syntax Simulate keystrokes and mouse movements Manipulate windows and processes Interact with all standard windows controls Scripts can be compiled into standalone executables Create Graphical User Interfaces (GUIs) COM support Regular expressions Directly call external DLL and Windows API functions Scriptable RunAs functions Detailed helpfile and large community-based support forums Compatible with Windows 95 / 98 / ME / NT4 / 2000 / XP / 2003 / Vista / 2008 Unicode and x64 support Digitally signed for peace of mind Works with Windows Vista's User Account Control (UAC) AutoIt has been designed to be as small as possible and stand-alone with no external .dll files or registry entries required making it safe to use on Servers. Scripts can be compiled into stand-alone executables with Aut2Exe. Also supplied is a combined COM and DLL version of AutoIt called AutoItX that allows you to add the unique features of AutoIt to your own favourite scripting or programming languages! Also, AutoIt comes with an extremely powerful text editor called SciTE4AutoIt3. The following info comes from the autoit web page as well: Quote Neil Hodgson:"SciTE is a SCIntilla based Text Editor. Originally built to demonstrate Scintilla, it has grown to be a generally useful editor with facilities for building and running programs." SciTE4AutoIt3 contains SciTE, wrapped into a single installer with all needed configuration settings and lots of utility programs like Tidy, Obfuscator, AU3Check, ScriptWriter, AutoIt3Wrapper etc to enhanced SciTE for use with AutoIt3. It has a customized Lexer for AutoIt3 which handles the Syntax Highlighting and Code folding: CodeFolding: Autocomplete: Intellisense: This customized version of SciTE has the following functionality: Customized Syntax highlighting. AutoComplete AutoIt3 commands automatically (suggest the option in a dropdownbox while typing), just hit ENTER or TAB to Autocomplete.) AutoComplete anything already in the script, like variable and Func names, with Ctrl+Enter. Intellisense (Show a ToolTip with the parameter expected in the selected function). Code folding for easy code viewing. Auto indentation while typing. F1 - open Helpfile on the keyword were the cursor is located. Shift+F1 will bring up a Popup screen showing all AutoIt3 functions. Just Double-Click or Enter on the function you need and it will be pasted back into your script. It Also has a dynamic Help facility! Ctrl+F1 - open this Helpfile. F5 - Run Tylo's Au3Check and when no errors/warnings found run AutoIt3.exe. Ctrl+F5 - Run Tylo's SyntaxCheck With latest Production definitions, showing all Syntax errors and possible issues with variable declarations. Ctrl+Alt+F5 - Run Tylo's SyntaxCheck With latest Beta definitions, showing all Syntax errors and possible issues with variable declarations. Alt+F6 - Run Larry's ScriptWriter to record clicks and keystrokes and write this into your Autoit Script. Ctrl+F6 - Run Larry's AU3_Spy program to detect the Text and Names of controls on the program windows. F7 - Build (compile) your script. Alt+F7 - Run VoSs2o0o's AutoItMacroGenerator ...Another recorder for script. Ctrl+F7 - AutoIt3Wrapper: Build (compile) your script with Options to change Compiler version, ICON, Passphrase or compression, Update Resource info of the target program like Program version etc. Optional run Tylo's AU3Check before compiling the source and running other programs Before or After compilation. Ctrl+T will run Tidy.exe (included in this install) to auto indent and Tidy your AutoIt3 source file. Alt+M will run CodeWizard.exe written by Peppe which assists you in creating MsgBox or InputBox() statements. Alt+G will run GuiWizard.exe written by CyberSlug which assists you in creating GUI Layouts. Ctrl+Alt+s will Run the Snippet holder . Several LUA scripts to enhance SciTE editing. o Insert a copy of the Bookmarked line(s) - Ctrl+Alt+B This functions will insert all Bookmarked lines at the beginning for the current line. Lines can be Bookmarked by pressing Ctrl+F2. o Jump to the "Func ???" definition of the functionname under the Cursor - Ctrl+J. It will also Bookmark the original line to enable you to jump back to the original line with F2. o List dropdownbox Ctrl+L with all available Func's in the current script and jumps to selected script. It will also Bookmark the original line to enable you to jump back to the original line with F2. o Ctrl+Shift+D - Add Debug msgbox This function will add a MSGBOX below the current line that contains the Var the cursor is at $a = $b + 1 (Put the cursor on $b and press Ctrl+Shift+D the following line will be added) MsgBox(4096,'debug:' & $b,$b) ;### Debug MSGBOX o Alt+D - Add Debug ConsoleWrite message This function will add a ConsoleWrite line below the current line that contains the Var the cursor o o o o is at $a = $b + 1 (Put the cursor on $b and press Alt+D the following line will be added) ConsoleWrite('Line:~4 debug ==> $b: ' & $b & @lf) ;### Debug Console Alt+Shift+D - Comment ALL DEBUG MsgBox and ConsoleWrite lines. Ctrl+Alt+D - UnComment ALL Debug MsgBoxes and ConsoleWrite lines. Add TRACE ConsoleWrites to all lines to easily trace your program:Available under Tools/Debug: Add Trace lines Remove ALL Debug MsgBoxes and ConsoleWrite lines: Available under Tools/Debug: Remove ALL lines And, here is a VERY useful set of commonly used example functions, keywords, and macros that autoit supports (this is NOT the complete set by any means): Functions Abs - Calculates the absolute value of a number ACos - Calculates the arcCosine of a number AdlibDisable - Disables the adlib functionality AdlibEnable - Enables Adlib functionality Asc - Returns the ASCII code of a character ASin - Calculates the arcsine of a number ATan - Calculates the arctangent of a number AutoItSetOption - Changes the behavior of several AutoIt functi... AutoItWinGetTitle - Retrieves the title of the AutoIt window AutoItWinSetTitle - Changes the title of the AutoIt window BitAND - Performs a bitwise AND operation BitNOT - Performs a bitwise NOT operation BitOR - Performs a bitwise OR operation BitShift - Performs a bit shifting operation BitXOR - Performs a bitwise exclusive OR (XOR) operati... BlockInput - Disable/enable the mouse and keyboard Break - Enables or disables the users' ability to exi... Call - Calls a user-defined function contained in a ... CDTray - Opens or closes the CD tray Chr - Returns a character corresponding to an ASCII... ClipGet - Retrieves text from the clipboard ClipPut - Writes text to the clipboard ControlClick - Sends a mouse click command to a given contro... ControlCommand - Sends a command to a control ControlDisable - Sends a command to a control ControlEnable - Enables a disabled control ControlFocus - Sets input focus to a given control on a wind... ControlGetFocus - Returns the control reference number of the c... ControlGetHandle - Gets the internal handle of a control ControlGetPos - Retrieves the position and size of a control ... ControlGetText - Retrieves text from a control ControlHide - Hides a control ControlListView - Sends a command to a ListView control ControlMove - Moves a control within a window ControlSend - Sends a string of characters to a control ControlSetText - Sets text of a control ControlShow - Shows a control that was hidden Cos - Calculates the cosine of a number Dec - Returns a numeric representation of a hexadec... DirCopy - Copies a directory and all subdirectories an... DirCreate - Creates a directory DirGetSize - Returns the size of a specified directory in ... DirMove - Moves a directory and all subdirectories and... DirRemove - Deletes a directory DllCall - Dynamically calls a function in a DLL DllClose - Closes a previously opened DLL DllOpen - Opens a dll file for use in DllCall DriveGetDrive - Returns an array containing the enumerated dr... DriveGetFileSystem - Returns File System Type of a drive DriveGetLabel - Returns Volume Label of a drive, if it has on... DriveGetSerial - Returns Serial Number of a drive DriveGetType - Returns drive type DriveMapAdd - Maps a network drive DriveMapDel - Disconnects a network drive DriveMapGet - Retreives the details of a mapped drive DriveSetLabel - Sets the Volume Label of a drive DriveSpaceFree - Returns the free disk space of a path in Mega... DriveSpaceTotal - Returns the total disk space of a path in Meg... DriveStatus - Returns the status of the drive as a string EnvGet - Retrieves an environment variable EnvSet - Writes an environment variable EnvUpdate - Refreshes the OS environment Eval - Return the value of the variable whose name i... Exp - Calculates e to the power of a number FileChangeDir - Changes the current working directory FileClose - Closes a text file FileCopy - Copies one or more files FileCreateShortcut - Creates a shortcut to a file FileDelete - Delete one or more files FileExists - Checks if a file or directory exists FileFindFirstFile - Returns a filename according to search string FileFindNextFile - Returns a filename according to search string FileGetAttrib - Returns a code string representing a file's a... FileGetLongName - Returns the long path and filename of the pat... FileGetShortcut - Retrieves details about a shortcut FileGetShortName - Returns the 8.3 (short) path and filename of ... FileGetSize - Returns the size of a file in bytes FileGetTime - Returns the time and date information for a f... FileGetVersion - Returns the "File" version information FileInstall - Include and install a file with the compiled ... FileMove - Moves one or more files FileOpen - Opens a text file for reading or writing FileOpenDialog - Initiates a Open File Dialog FileRead - Read in a number of characters from a previou... FileReadLine - Read in a line of text from a previously open... FileRecycle - Sends a file or directory to the recycle bin,... FileRecycleEmpty - Empties the recycle bin FileSaveDialog - Initiates a Save File Dialog FileSelectFolder - Initiates a Browse For Folder GUI FileSetAttrib - Sets the attributes of one or more files FileSetTime - Sets the timestamp of one of more files FileWrite - Append a line of text to the end of a previou... FileWriteLine - Append a line of text to the end of a previou... FtpSetProxy - Sets the internet proxy to use for ftp access GUICreate - Creates a GUI window GUICtrlCreateAVI - Creates an AVI video control for the GUI GUICtrlCreateButton - Creates a Button control for the GUI GUICtrlCreateCheckbox - Creates a Checkbox control for the GUI GUICtrlCreateCombo - Creates a ComboBox control for the GUI GUICtrlCreateContextMenu - Creates a context menu for a control or entir... GUICtrlCreateDate - Creates a date control for the GUI GUICtrlCreateDummy - Creates a Dummy control for the GUI GUICtrlCreateEdit - Creates an Edit control for the GUI GUICtrlCreateGroup - Creates a Group control for the GUI GUICtrlCreateIcon - Creates an Icon control for the GUI GUICtrlCreateInput - Creates an Input control for the GUI GUICtrlCreateLabel - Creates a static Label control for the GUI GUICtrlCreateList - Creates a List control for the GUI GUICtrlCreateListView - Creates a ListView control for the GUI GUICtrlCreateListViewItem - Creates a ListView item GUICtrlCreateMenu - Creates a Menu control for the GUI GUICtrlCreateMenuitem - Creates a MenuItem control for the GUI GUICtrlCreatePic - Creates a Picture control for the GUI GUICtrlCreateProgress - Creates a Progress control for the GUI GUICtrlCreateRadio - Creates a Radio button control for the GUI GUICtrlCreateSlider - Creates a Slider control for the GUI GUICtrlCreateTab - Creates a Tab control for the GUI GUICtrlCreateTabItem - Creates a TabItem control for the GUI GUICtrlCreateTreeView - Creates a TreeView control for the GUI GUICtrlCreateTreeViewItem - Creates a TreeViewItem control for the GUI GUICtrlCreateUpdown - Creates an UpDown control for the GUI GUICtrlDelete - Deletes a control GUICtrlGetState - Gets the current state of a control GUICtrlRead - Read state or data of a control GUICtrlRecvMsg - Send a message to a control and retrieve info... GUICtrlSendMsg - Send a message to a control GUICtrlSendToDummy - Sends a message to a Dummy control GUICtrlSetBkColor - Sets the background color of a control GUICtrlSetColor - Sets the text color of a control GUICtrlSetCursor - Sets mouse cursor icon for a particular contr... GUICtrlSetData - Modifies the data for a control GUICtrlSetFont - Sets the font for a control GUICtrlSetImage - Sets the bitmap or icon image to use for a co... GUICtrlSetLimit - Limits the number of characters/pixels for a ... GUICtrlSetOnEvent - Defines a userdefined function to be called ... GUICtrlSetPos - Changes the position of a control within the ... GUICtrlSetResizing - Defines the resizing method used by a control GUICtrlSetState - Changes the state of a control GUICtrlSetStyle - Changes the style of a control GUICtrlSetTipf - Sets the tip text associated with a control GUIDelete - Deletes a GUI window and all controls that it... GUIGetCursorInfo ([]) - Gets the mouse cursor position relative to GU... GUIGetMsg - Polls the GUI to see if any events have ocurr... GUISetBkColor - Sets the background color of the GUI window GUISetCoord - Sets absolute coordinates for next control GUISetCursor - Sets the mouse cursor icon for a GUI window GUISetFont - Sets the default font for a GUI window GUISetHelp - Sets an executable file that will be run when... GUISetIcon - Sets the icon used in a GUI window GUISetOnEvent - Defines a user function to be called when a c... GUISetState - Changes the state of a GUI window GUIStartGroup - Defines that any subsequent controls that are... GUISwitch - Switches the current window used for GUI func... Hex - Returns a string representation of an integer... HotKeySet - Sets a hotkey that calls a user function HttpSetProxy - Sets the internet proxy to use for http acces... InetGet - Downloads a file from the internet using the ... InetGetSize - Returns the size of a file located on the Int... IniDelete - Deletes a value from a standard format .ini f... IniRead - Reads a value from a standard format .ini fil... IniReadSection - Reads all key/value pairs from a section in a... IniReadSectionNames - Reads all sections in a standard format .ini ... IniWrite - Writes a value to a standard format .ini file InputBox - Displays an input box to ask the user to ente... Int - Returns the integer representation of an expr... IsAdmin - Checks if the current user has administrator ... IsArray - Checks if a variable is an array type IsDeclared - Check if a variable has been declared IsFloat - Checks if a variable or expression is a float... IsInt - Checks if a variable or expression is an inte... IsNumber - Checks if a variable's base type is numeric IsString - Checks if a variable is a string type Log - Calculates the natural logarithm of a number MemGetStats - Retrieves memory related information Mod - Performs the modulus operation MouseClick - Perform a mouse click operation MouseClickDrag - Perform a mouse click and drag operation MouseDown - Perform a mouse down event at the current mou... MouseGetCursor - Returns a cursor ID Number of the current Mou... MouseGetPos - Retrieves the current position of the mouse c... MouseMove - Moves the mouse pointer MouseUp - Perform a mouse up event at the current mouse... MouseWheel - Moves the mouse wheel up or down MsgBox - Displays a simple message box with optional t... Number - Returns the numeric representation of an expr... Ping - Pings a host and returns the roundtrip-time PixelChecksum - Generates a checksum for a region of pixels PixelGetColor - Returns a pixel color according to x,y pixel ... PixelSearch - Searches a rectangle of pixels for the pixel ... ProcessClose - Terminates a named process ProcessExists - Checks to see if a specified process exists ProcessList - Returns an array listing the currently runnin... ProcessSetPriority - Changes the priority of a process ProcessWait - Pauses script execution until a given process... ProcessWaitClose - Pauses script execution until a given process... ProgressOff - Turns Progress window off ProgressOn - Creates a customizable progress bar window ProgressSet - Sets the position and/or text of a previously... Random - Generates a pseudo-random float-type number RegDelete - Deletes a key or value from the registry RegEnumKey - Reads the name of a subkey according to it's ... RegEnumVal - Reads the name of a value according to it's i... RegRead - Reads a value from the registry RegWrite - Writes a value to the registry Round - Returns a number rounded to a specified numbe... Run - Runs an external program RunAsSet - Initialise a set of user credentials to use d... RunWait - Runs an external program and pauses script ex... Send - Sends simulated keystrokes to the active wind... SetError - Manually set the value of the @error macro SetExtended - Manually set the value of the @extended macro Shutdown - Shuts down the system Sin - Calculates the sine of a number Sleep - Pause script execution SoundPlay - Play a sound file SoundSetWaveVolume - Sets the system wave volume by percent SplashImageOn - Creates a customizable image popup window SplashOff - Turns SplashText or SplashImage off SplashTextOn - Creates a customizable text popup window Sqrt - Calculates the square-root of a number StatusbarGetText - Retrieves the text from a standard status bar... String - Returns the string representation of an expre... StringAddCR - Takes a string and prefixes all linefeed char... StringFormat - Returns a formatted string (similar to the C ... StringInStr - Checks if a string contains a given substring... StringIsAlNum - Checks if a string contains only alphanumeric... StringIsAlpha - Checks if a string contains only alphabetic c... StringIsASCII - Checks if a string contains only ASCII charac... StringIsDigit - Checks if a string contains only digit (0-9) ... StringIsFloat - Checks if a string is a floating point number StringIsInt - Checks if a string is an integer StringIsLower - Checks if a string contains only lowercase ch... StringIsSpace - Checks if a string contains only whitespace c... StringIsUpper - Checks if a string contains only uppercase ch... StringIsXDigit - Checks if a string contains only hexadecimal ... StringLeft - Returns a number of characters from the left-... StringLen - Returns the number of characters in a string StringLower - Converts a string to lowercase StringMid - Extracts a number of characters from a string StringReplace - Replaces substrings in a string StringRight - Returns a number of characters from the right... StringSplit - Splits up a string into substrings depending ... StringStripCR - Removes all carriage return values from a str... StringStripWS - Strips the white space in a string StringTrimLeft - Trims a number of characters from the left ha... StringTrimRight - Trims a number of characters from the right h... StringUpper - Converts a string to uppercase Tan - Calculates the tangent of a number TimerDiff - Returns a difference in time from a previous ... TimerInit - Returns a time stamp in milliseconds with acc... ToolTip - Creates a tooltip anywhere on the screen TrayTip - Displays a balloon tip from the AutoIt Icon UBound - Returns the size of array dimensions WinActivate - Sets focus to a window WinActive - Checks to see if a specified window exists an... WinClose - Closes a window WinExists - Checks to see if a specified window exists WinGetCaretPos - Returns the coordinates of the caret in the f... WinGetClassList - Retrieves the classes from a window WinGetClientSize - Retrieves the size of a given window's client... WinGetHandle - Retrieves the internal handle of a window WinGetPos - Retrieves the position and size of a given wi... WinGetProcess - Retrieves the Process ID (PID) associated wit... WinGetState - Retrieves the state of a given window WinGetText - Retrieves the text from a window WinGetTitle - Retrieves the full title from a window WinKill - Forces a window to close WinList - Retrieves a list of windows WinMenuSelectItem - Invokes a menu item of a window WinMinimizeAll - Minimizes all windows WinMinimizeAllUndo - Undoes a previous WinMinimizeAll function WinMove - Moves and/or resizes a window WinSetOnTop - Change a window's "Always On Top" attribute WinSetState - Shows, hides, minimizes, maximizes, or restor... WinSetTitle - Changes the title of a window WinSetTrans - Sets the transparency of a window WinWait - Pauses execution of the script until the requ... WinWaitActive - Pauses execution of the script until the requ... WinWaitClose - Pauses execution of the script until the requ... WinWaitNotActive - Pauses execution of the script until the requ... Keywords #ce - Identifies the end of comment lines not to be... #comments-end - Identifies the end of comment lines not to be... #comments-start - Identifies the start of comment lines not to ... #cs - Identifies the start of comment lines not to ... #include - Includes the contents of another script in th... #include-once - Keeps a script from being included in another... #NoTrayIcon - Indicates that the AutoIt tray icon will not ... Case - Specifies a condition to evaluate in a Select... ContinueLoop - Instructs script to continue a loop statement Dim - Declare a variable or create an array Do - Loop based on an expression Else - Identifies the statement to process if the co... ElseIf - Identifies an additional expression to be han... EndFunc - Identifies the end of the code for a user def... EndIf - Marks the end of a If/Else statement EndSelect - Marks the end of a conditional Select stateme... Exit - Terminates the script ExitLoop - Terminate a While/Do/For loop For - Loop based on an expression Func - Defines a user-defined function that takes ze... Global - Creates a variable in the Global scope If - Conditionally run a statement Local - Creates a variable in the Local/Function scop... Next - Marks the end of a For loop ReDim - Resize an existing array Return - Exits a function Select - Conditionally run statements Then - Identifies statement to run if conditional If... Until - Loop based on an expression WEnd - Marks the end of a While loop While - Loop based on an expression Macros @AppDataCommonDir - Path to Application Data folder @AppDataDir - Path to current user's Application Data @AutoItVersion - Version number of AutoIt @CommonFilesDir - Path to Common Files folder @Compiled - Identifies if script is running as a complied... @ComputerName - Computer's network name @ComSpec - Path and file name of command interpreter @CR - Carriage return @CRLF - Carriage return and line feed @DesktopCommonDir - Path to Desktop @DesktopDepth - Depth of the desktop screen in bits per pixel @DesktopDir - Path to current user's Desktop @DesktopHeight - Height of screen in pixels @DesktopWidth - Width of screen in pixels @DocumentsCommonDir - Path to Documents @Error - Status of the error flag @FavoritesCommonDir - Path to Favorites @FavoritesDir - Path to current user's Favorites @HomeDrive - Drive letter of drive containing current user... @HomePath - Directory part of current user's home directo... @HomeShare - Server and share name containing current user... @Hour - Hours value of clock in 24-hour format @IPAddress1 - IP address of first network adapter @IPAddress2 - IP address of second network adapter @IPAddress3 - IP address of thrid network adapter @IPAddress4 - IP address of fourth network adapter @LF - Line feed @LogonDNSDomain - Logon DNS Domain @LogonDomain - Logon Domain @LogonServer - Logon server @MDay - Current day of month @Min - Minutes value of clock @Mon - Current month @MyDocumentsDir - Path to My Documents target @OSBuild - Returns the OS build number @OSLang - Returns code denoting OS Language @OSServicePack - Service pack info @OSType - Identifies NT or later versions of Windows @OSVersion - Version of Windows as text string @ProgramFilesDir - Path to Program Files folder @ProgramsCommonDir - Path to Start Menu's Programs folder @ProgramsDir - Path to current user's Programs (folder on St... @ScriptDir - Directory containing the running script. @ScriptFullPath - Full path and name of current script @ScriptName - Long filename of the running script @Sec - Seconds value of clock @StartMenuCommonDir - Path to Start Menu folder @StartMenuDir - Path to current user's Start Menu @StartupCommonDir - Path to Startup folder @StartupDir - Current user's Startup folder @SW_Hide - Hide window @SW_Maximize - Maximize window @SW_Minimize - Minimize window @SW_Restore - Undoes a window minimization or maximization @SW_Show - Shows a previously hidden window @SW_ShowDefault - Sets the show state based on the SW_ value sp... @SW_ShowMaximized - Activates the window and displays it as a max... @SW_ShowMinimized - Activates the window and displays it as a min... @SW_ShowMinNoActive - Displays the window as a minimized window. @SW_ShowNA - Displays the window in its current size and p... @SW_ShowNoActivate - Displays a window in its most recent size and... @SW_ShowNormal - Activates and displays a window @SystemDir - Path to the Windows System (or System32) fold... @Tab - Tab character @TempDir - Path to the temporary files folder @UserName - ID of the currently logged on user @UserProfileDir - Path to current user's Profile folder @WDay - Numeric day of week @WindowsDir - Path to Windows folder <> @WorkingDir - Current/active working directory @YDay - Current day of year @Year - Current four-digit year