Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 03/30/2023 in all areas

  1. It's been a while. But here we are again, finally, with another update. Check the first post for v1.0.0-beta4. I'm excited to announce the new undo/redo functionality, which makes this little program 100x more useful (in my humble opinion). I'm sure there are lots of bugs to be found. Let me know! Highlights: FIXED: Jumping while resizing ADDED: Undo / redo functionality ADDED: Change window title to match Title property UPDATED: More sophisticated handling of AutoIt3.exe location UPDATED: Updated About dialog
    5 points
  2. Hello Again! I previously stumbled upon a topic asking for maps datatype's instructions... I too wasn't sure what a map is until I tried it... So I am making this topic to help other newbies (and some oldbies) better understand the Maps datatype of AutoIt! Lets start! A Note for Readers The maps datatype is still in development and is currently in Alpha Stage (More Risky than Beta) and its unstable, so AutoIt can crash indefinably while using Maps! I can't guarantee if this will be implemented in stable versions, this is a fairly new thing to AutoIt coders & in my honest opinion I don't see any use for it Maps are the best datatype in AutoIt, Very Useful ... Not hurting anyone though . Also the maps datatype is DISABLED IN STABLE VERSIONS, So you need to install the latest beta version of AutoIt to make maps work . If you find any bugs while using a map, please report it in the Official Bug Tracker Introduction To Maps Maps are just like arrays, instead they use "keys" to access elements inside them... A key can be either a string or an integer (Other datatypes work too but they are converted to a integer [Equivalent to Int($vKey)] before assignment [Source]). Although Integers don't represent the order of elements in a map unlike in an array... Declaring Maps Its similar to declaring an Array: ; This is the only way to declare a map ; You must have a declarative keyword like Dim/Global/Local before the declaration unless the map is assigned a value from a functions return Local $mMap[] ; Don't insert any numbers or strings it! Simple, Isn't it? Using Maps Using maps is similar to arrays (again!): Local $mMap[] ; Lets declare our map first! ; Adding data to maps is easy... ; This is our key ; | ; v $mMap["Key"] = "Value" ; <--- And our value! ; A key is Case-Sensitive meaning "Key" is not same as "key"! $mMap["key"] = "value" ; Not the same as $mMap["Key"]! ; There are 2 different ways to access an element in a map $mMap["Key"] ; 1st Method $mMap.Key ; 2nd Method Enumerating Maps Its quite easy to enumerate through arrays but what about maps? how can I enumerate through them!? #include <MsgBoxConstants.au3> ; Lets create our map first Local $mMap[] ; Lets add some information to the map, feel free to modify & add new elements $mMap["Name"] = "Damon Harris" $mMap["Alias"] = "TheDcoder" $mMap["Gender"] = "Male" $mMap["Age"] = 14 $mMap["Location"] = "India" $aMapKeys = MapKeys($mMap) ; MapKeys function returns all the keys in the format of an array Local $sProfile = "Profile of " & $mMap["Name"] & ':' & @CRLF ; We will use this string later For $vKey In $aMapKeys ; We use this to get the keys in a map :) $sProfile &= @CRLF & $vKey & ': ' & $mMap[$vKey] ; Add some details to the profile string using our map! Next MsgBox($MB_ICONINFORMATION + $MB_OK, "Profile", $sProfile) ; Finally display the profile :) It is easy as always Multi-Dimensional Maps Now now... I know that you are a little confused that how can an multi-dimensional maps exist... Although I am not 100% sure if its called that but lets continue: #include <MsgBoxConstants.au3> ; Multi-Dimensional maps are just maps in a map Local $mMapOfMapsvilla[] ; This map will store an other map Local $mParkMap[] ; This Park map will be inserted in the Mapsvilla's map :P $mMapOfMapsvilla["Map Item 1"] = "Town Hall" $mMapOfMapsvilla["Map Item 2"] = "Police Station" $mMapOfMapsvilla["Map Item 3"] = "Shopping Mall" $mMapOfMapsvilla["Map Item 4"] = "Residential Area" $mMapOfMapsvilla["Map Item 5"] = "Park" $mParkMap["Map Item 1"] = "Cottan Candy Stand" $mParkMap["Map Item 2"] = "Public Toilet" $mParkMap["Map Item 3"] = "Woods" $mMapOfMapsvilla.Park = $mParkMap MsgBox($MB_OK, "Map Location", $mMapOfMapsvilla["Map Item 1"]) ; Will display Town Hall MsgBox($MB_OK, "Map Location", $mMapOfMapsvilla.Park["Map Item 1"]) ; Will display Cottan Candy Stand I am sure its easy for you to understand now Frequently Asked Questions (FAQs) & Their answers Q #1. Help! My code does not respond to anything (or) I get an "Variable subscript badly formatted" error on the line of declaration... A. DONT USE F5 or Go, Instead use Alt + F5 or Tools -> Beta Run in SciTE (Make sure that you have Beta installed) Q #2. Why are you using "m" in-front of every map variable? A. Best coding Practices: Names of Variables Q #3. What are "Elements" which you mention frequently??? A. This is a newbie question (I have no intention of insulting you ), so I guess you are new to programming. "Elements" are data slots inside a Map (or an Array), you can imagine elements as individual variable which are stored in a Map. You can access them using "keys", Please refer to "Introduction to Maps" section at the starting of this post Q #4. Are Maps faster than Arrays? A. You need to understand that Maps have different purpose than Arrays. Maps are designed to store data dynamically (like storing information for certain controlIDs of GUI) and Arrays are designed to store data in a order (for instance, Storing every character of a string in an element for easy access). If you still want to know then if Maps are faster, then the answer is maybe... Maps are *supposed* (I am not sure ) to be faster in addition of elements (while Arrays are painfully slow while adding or removing elements). Here (Post #24) is a benchmark (Thanks kealper! ) More FAQs coming soon! Feel free to ask a question in the mean while
    1 point
  3. Jfish

    Chat GPT example

    CHAT GPT is taking over ... so I asked it to help me code a call to itself from AutoIt. It did pretty well - but ultimately I had to turn to the docs to realize that it was calling its own deprecated endpoint that I needed to update (AI has limits I guess). Anywho, if anyone wants to play around with it here is a working example: #include <WinHttp.au3> #include <Json.au3> ; Set up WinHttp object $oHttp = ObjCreate("WinHttp.WinHttpRequest.5.1") $oHttp.Open("POST", "https://api.openai.com/v1/completions", false) $oHttp.SetRequestHeader("Content-Type", "application/json") $oHttp.SetRequestHeader("Authorization", "Bearer <YOUR API KEY HERE>"); you will need to get an API key and place it here ; Set up request data params can be seen here https://platform.openai.com/docs/api-reference/completions/create ; tokens dictate length $sData = '{"model": "text-davinci-003", "prompt": "what day is it?", "max_tokens": 10}' ; change the prompt to whatever you want ; Send request and get response $oHttp.Send($sData) ; Check if request was successful If $oHttp.Status <> 200 Then MsgBox(0, "Error", "WinHttp request failed with status code: " & $oHttp.Status) Exit EndIf $sResponse = $oHttp.ResponseText ; Parse response and display $aJson = _Json_Parse($sResponse) $sText = $aJson.choices[0].text MsgBox(0, "Response", $sText)
    1 point
  4. Simulated Annealing (SA) is a simple technique for finding an acceptable solution (but not necessarily always the absolute best one that exists!) to very hard combinatorial problems, that is, ones for which a brute-force approach of cycling through all possible alternatives to find the global optimum just takes too darn long. Typically, one would be seeking some specific sequence or permutation of a (sub)set, and the number of possibilities is astronomically large. In addition, for SA to be applicable, you'll need to be able to quantify in some way how good any particular trial solution is, or how far distant from the ideal result. The real power of SA lies in these so-called cost functions; you can define as many as you like, with different weights if you like, and these conditions are even allowed to be conflicting. User-defined settings define how tenaciously it should be exploring solution space before homing in on a region with desirable properties, and finding its minimum. You can think of it as a learning algorithm that is allowed to make lots of mistakes in the beginning, before gradually avoiding ever more potentially bad decisions. A simple Analogy: You're standing in the middle of an extensive, rough terrain with hills, ridges, bumps, valleys, and tiny, deep depressions. You've got a GPS altimeter to tell you how high above sea-level you currently are, but this area is perpetually shrouded in thick fog. Now find the lowest point. And quickly please. Now what? There's no time to systematically grid and traverse the entire area, and you cannot see more than a few feet ahead. Following the local gradient down-slope will likely get you stuck at a very local minimum, whereas a much lower point may be just beyond the hext hill. Luckily, you brought your magic boots (the red ones with the twinkling silver stars). These allow you to make huge leaps through the fog, landing safely somewhere else. And although you don't know in advance where you'll end up, the boots magically remember their last-previous departure point, so if you don't like your new surroundings, you can go back one jump (but never more than that). Now to find the lowest point in the landscape, you keep tracking your altimeter changes with every jump. Some jumps will get you to higher ground, others might land you in a deep valley. The trick is not to settle for ever-lower heights immediately, but to allow going back up ever so often, so you can get beyond some high ridge behind which you might find a much lower depression than your best-previous result. Crucially, to decide whether or not to gain height in the misty terrain, you roll some dice you've got in your pocket, and the more jumps you've made, the lower you make the upper bound below which you would still go back uphill. So in the beginning you'll be jumping all over the place (allowing you to sample the terrain extensively), but eventually you'll be limiting yourself to some deep valley you've found, which might be the deepest one all round, but even if not, it will still be a pretty good guess. And you will have found this deep valley in a tiny fraction of the time it would take to do a full land survey. Simulated annealing needs to be defined in terms of the specific problem you're trying to solve. So it's not possible to provide you with a generic UDF that'll figure out in advance what your ideal solution would look like (for example, in the analogy above, we might be looking for the highest point instead of the lowest one). You need to define that ideal in terms of one or more cost functions that SA will then attempt to minimise. What can be done is to provide you with specific examples. Example 1. From a list of user-defined pre-supplied values, select the fewest terms that sum to (or approximate) a predefined target total. This solution was written in response to this thread. Current cost updates are periodically written to console. This example attempts to satisfy two conditions simultaneously: getting a sum that matches the target, and using the smallest number of terms. ; Simulated Annealing example (combinatorial minimisation), by RTFC (22 Feb 2016) ; Note that this algorithm converges on A *local* minimum (in terms of the ; user-defined cost-function(s)), which is not necessarily THE *global* minimum. ; Note also that the search path, duration, and final result may differ from run to run. ; Several parameters can be tweaked to adjust this. #include <Array.au3> #include <Math.au3> Global $temperat,$path,$kk,$nswap,$nswapstep,$cost,$altcost,$tempstep Global $costadjust,$ttlsites,$totalcost,$factor,$maxsumlength,$maxsize Global $site1,$site2,$index1,$index2,$weight_sum,$weight_length Global $options,$sumlength,$prevlength ; initialise SRandom(@SEC+@AutoItPID) ; initialise radnomising seed $verbose=True ; T: write regular progress updates to console $factor=1 ; optional Oracle-response adjustment (not used here) $prevlength=$sumlength ; to enable reverting to previous state after _TryChange $minsumlength=0 ; if nothing else is know, we'll start with a single array entry (base-0) $options=10 ; larger value = larger likelihood of swapping vs changing sumlength if $options<3 then Exit ; minimum size for this set-up (see Func _TrySwap) ; adjust the balance of conditions here (see _Cost function) $weight_sum=1 ; relative importance of matching condition 1 (sum = target) $weight_length=1 ; relative importance of matching condition 2 (lowest number of terms) ; summation results buffer Global $bestsum[10] Global $bestsumlength=UBound($bestsum) ; define the summation result we wish to achieve (try different values here!) $target = 27 ; Note: if you change this value, you may have to adjust $minsumlength below as well! ; define our array of summation terms to select from $dim=9 ; this is just the way this problem was presented $ttlsites=$dim*$dim $maxsize=$ttlsites-1 $maxsumlength=$ttlsites-2 ; need at least one tail slot for swapping ; enable this for the predefined problem... $doIntegerTest=True ; False if $doIntegerTest Then Global $aArray = [9,2,2,3,1,1,6,3,4, _ 4,2,3,4,5,6,7,8,7, _ 7,2,3,4,5,1,7,2,2, _ 2,2,3,1,5,5,7,1,4, _ 3,2,1,2,3,6,6,6,4, _ 3,2,3,4,5,6,7,8,3, _ 2,2,3,8,1,4,7,1,2, _ 1,7,3,5,5,6,7,1,2, _ 7,2,3,7,5,1,7,8,9] ; in this specific case, we already know that we'll need at least 4 terms ; because a) 9=max value in array, b) there are only 2 nines in the array, and c) target =3x9 $minsumlength=3 ; base-0, so 4 entries altogether Else ; OR use this for random floats in range 1-$dim (just as an example) Global $aArray[$ttlsites] For $cc=0 to $maxsize $aArray[$cc]=random(1,$dim,0) ; non-integer values used here! Next ; no clue about this constraint in this case $minsumlength=0 ; one entry (base-0) EndIf ;______START OF ANNEALING ROUTINE____________ $nover =1000 ; maximum number of changes at any temperature (for more complicated problems, set this several orders of magnitude higher) $nlimit=Int($nover/4) ; maximum number of successful changes before continuing $nwrite=Int($nover/5) ; default status update interval if verbose=.t. $tempsteps=100 ; number of temperature steps to try $tfactor=0.95 ; annealing schedule: temperature is reduced by this factor after each step While True $temperat=0.5 ; initial temperature; smaller = more aggressive + more myopic search $absimp=0 ; counter $nswapstepzero=0 ; counter $sumlength=$minsumlength ; base-0 ; prep the cost vars $totalcost=_Cost() $cost=$totalcost $lowestcost=$totalcost $initcost=$totalcost ; main loop starts here For $tempstep=1 to $tempsteps ; try up to N temperature steps $nswap=0 $nswapstep=0 For $kk=1 to $nover _TrySwap() ; swap and determine cost adjustment Switch _AskOracle() ; Feel the Force, Luke. Case True $nswap+=1 $totalcost+=$costadjust $cost=$altcost If $lowestcost>$totalcost Then $nswapstep+=1 $absimp+=1 $lowestcost=$totalcost ; ensure results buffer is sufficiently large If $bestsumlength<=$sumlength Then $bestsumlength+=5 ReDim $bestsum[$bestsumlength] EndIf ; flush current-best summation For $bc=0 to $sumlength-1 $bestsum[$bc]=$aArray[$bc] Next ; pad tail with zeroes For $bc=$sumlength to $bestsumlength-1 $bestsum[$bc]=0 Next _ScreenOut() If $totalcost<=0 Then ExitLoop Endif Case Else ; restore the previous state $sumlength=$prevlength $aArray[$index1]=$site1 $aArray[$index2]=$site2 EndSwitch ; show we're still alive If $verbose And mod($kk,$nwrite)=0 Then _ScreenOut() If $nswap>=$nlimit Or $lowestcost<=0 then ExitLoop Next ; optional early-out scenario (disable for a more thorough search) If $nswapstep=0 then $nswapstepzero+=1 If $nswapstepzero=10 then ExitLoop ; no more improvements in the last N temperature steps ; reduce temperature = likelihood of following a trajectory away from the nearest LOCAL optimum (in the hope of getting nearer to the GLOBAL optimum) $temperat*=$tfactor Next ; present final result _Arraysort($bestsum) ; just for clarity $summation="Best result so far (at a cost of " & $lowestcost & ") is: " & @CRLF $terms=0 $result=0 For $cc=0 to $sumlength If $aArray[$cc]>0 then $summation&=$aArray[$cc] & "+" $result+=$aArray[$cc] $terms+=1 Endif Next $summation=StringTrimRight($summation,1) & " = " & $result & " (target = " & $target & ")" & @CRLF $summation&="Number of summation terms: " & $terms & @CR & "Temperature steps: " & $tempstep & @CR & @CR & "Press <Ok> to try again, <Cancel> to Quit" if Msgbox($MB_OKCANCEL,"Simulated Annealing Test Result",$summation)=$IDCANCEL then Exit ; shuffle entries a bit for variety For $cc=1 to $maxsize*10 $index1=random(0,$maxsize,1) $index2=random(0,$maxsize,1) $tmp=$aArray[$index1] $aArray[$index1]=$aArray[$index2] $aArray[$index2]=$tmp Next WEnd Exit Func _AskOracle() If $costadjust<0 Then Return True Else ; this is where all the magic happens! Return (random()<Exp(-($costadjust*$factor)/$temperat)) Endif EndFunc Func _TrySwap() $index1=0 ; these vars are all Globals $index2=0 $altcost=0 $prevlength=$sumlength ; decide whether to reduce/increase number of terms, or swap an existing term Switch Random(1,$options,1) Case 1 ; crop $sumlength=_Max($minsumlength,$sumlength-1) Case 2 ; extend $sumlength=_Min($maxsumlength,$sumlength+1) Case Else ; this likelhood is determined by the value of $options (>=3) $index1=random(0,$sumlength,1) $index2=random($sumlength+1,$maxsize,1) EndSwitch ; store current contents, in case we decide later that this was a bad idea $site1=$aArray[$index1] $site2=$aArray[$index2] ; swap contents for now $aArray[$index1]=$site2 $aArray[$index2]=$site1 ; compute the new sum (as either length or content has changed) $altcost=_Cost() ; performance difference between original and new state $costadjust=$altcost-$cost ; $cost is already filled in previous pass EndFunc Func _Cost() Local $cc,$result=0 For $cc=0 to $sumlength $result+=$aArray[$cc] Next Return (Abs($result-$target)*$weight_sum) + (($sumlength-$minsumlength)*$weight_length) EndFunc Func _ScreenOut() ConsoleWrite("Simulated Annealing. Initial total cost: " & $initcost & @CRLF) ConsoleWrite("Step: " & $tempstep & " of " & $tempsteps & "; Temperature: " & $temperat & @CRLF) ConsoleWrite("Executed Swaps: " & $nswap & "; Lowest Cost so far: " & $lowestcost & @CRLF) ConsoleWrite("Total Improvements: " & $absimp & "; Improvements this step: " & $nswapstep & @CRLF & @CRLF) EndFunc Example 2. The Travelling Salesman problem (TSP) This is a classic combinatorial minimisation problem, and relevant to real-world logistics: to find the shortest route for visiting all cities exactly once, before returning to the original starting point. As it is quite entertaining to see how the algorithm gradually solves this brain teaser, I've added a simple GUI that visualises the cities (red circles) and the changing routes between them (blue). The problem becomes exponentially harder to solve when the number of cities is increased. This example (adapted from Press et al., Numerical recipes, 2nd ed., pp. 438-443) employs a single cost function of the total route distance. TSP.au3 It's important to stress that simulated annealing cannot guarantee that the global optimum will always be found, only that it will likely come up with a fairly good solution, and much faster than brute force ever could. If that's good enough for you, then those red, silver-starred boots might fit you too.
    1 point
  5. Introduction JSON is a pure data exchange format. Basically you only have to deal with JSON in 2 places in a program: Once when reading JSON data and once when outputting data. In between it should not really matter that the data used to be JSON or should be converted to it. You should not need any special intermediate structures but only the elements that the respective programming language provides anyway. This is exactly the approach of this UDF: There is the function _JSON_Parse(), which converts an arbitrary JSON string into (nested) pure AutoIt data types (Arrays, Maps, Strings, Numbers, Null, True, False). And on the other side we have the function _JSON_Generate(), which generates a JSON string from arbitrary (nested) AutoIt data structures. Import and export JSON So how to use - let`s give an example: Handling nested data structures JSON is often very nested. The resulting AutoIt data is therefore naturally also nested, which makes it somewhat cumbersome to process with pure AutoIt on-board methods. For this reason, the UDF comes with a few helper functions that make life with this data easier. One of them is _JSON_Get(), which allows you to access deeply nested data with a simple query syntax. On the other hand there is the function _JSON_addChangeDelete() with which you can (the name already says it) change, add and delete data. You can even easily create deeply nested structures with a single call. Again, here is a small example of how to use it: Strictly speaking, these functions should not even have "JSON" in their names, since they are generally applied to data structures in AutoIt. However, since they are often used in the JSON environment, we allow ourselves this small inaccuracy. Why should i give it a try? Probably the most common method to deal with JSON in AutoIt is the variant via JSMN. My minor dissatisfactions with this approach led me to write this UDF in the first place a few years ago. So the incentives are quite JSMN related: Parsing and extraction of data is faster than in JSMN. (Only if the JSON string makes heavy use of JSON escapes should JSMN be a bit faster in parsing, since the escapes are resolved later.) Editing the data is easier, because you don't need special commands for the JSMN intermediate structure but deal directly with AutoIt structures. Generating JSON is also simple: build your structure in AutoIt as you like and then let it generate a JSON string for you with _JSON_Generate(). The UDF is smaller (28kb vs. 45kb) The UDF is in pure AutoIt. You can directly customize any behavior as you like. >>sourcecode and download on github<<
    1 point
  6. try this. $start = TimerInit() While 1 If TimerDiff($start) >= 9000 Then MsgBox(0, "time", " 9 seconds have passed ") Exit EndIf WEnd
    1 point
  7. Using DllCallAddress() is even faster, but as the team said, it's only worth to optimize when you've got a lot of calls, normally the bottlenecks are somewhere else. I analyzed how many calls are made in SMF and switched to DllCallAddress() for some calls of which literally million of calls where made in huge and complex searches. Overall gain I would say is max 5 to 10% in speed, now the hardware itself seems to be the bottleneck and slowest part in searching for files. #include <WinAPISys.au3> $iTimer = TimerInit() For $i = 1 To 1000000 _WinAPI_GetTickCount64() Next ConsoleWrite(_WinAPI_GetTickCount64() & @CRLF) ConsoleWrite(TimerDiff($iTimer) & @CRLF & @CRLF) $iTimer = TimerInit() For $i = 1 To 1000000 DllCall('kernel32.dll', 'uint64', 'GetTickCount64') Next ConsoleWrite(DllCall('kernel32.dll', 'uint64', 'GetTickCount64')[0] & @CRLF) ConsoleWrite(TimerDiff($iTimer) & @CRLF & @CRLF) $iTimer = TimerInit() $dll = DllOpen("kernel32.dll") For $i = 1 To 1000000 DllCall($dll, 'uint64', 'GetTickCount64') Next ConsoleWrite(DllCall($dll, 'uint64', 'GetTickCount64')[0] & @CRLF) DllClose($dll) ConsoleWrite(TimerDiff($iTimer) & @CRLF & @CRLF) $iTimer = TimerInit() Global $hInstance_Kernel32_dll = _WinAPI_GetModuleHandle("kernel32.dll") Global $hAddress_Kernel32_dll_GetTickCount64 = _WinAPI_GetProcAddress($hInstance_Kernel32_dll, "GetTickCount64") For $i = 1 To 1000000 DllCallAddress('uint64', $hAddress_Kernel32_dll_GetTickCount64) Next ConsoleWrite(DllCallAddress('uint64', $hAddress_Kernel32_dll_GetTickCount64)[0] & @CRLF) ConsoleWrite(TimerDiff($iTimer) & @CRLF & @CRLF)
    1 point
  8. Maybe not really needed anymore on Windows 10/11 and/or current version of AutoIt. I see it there as a "good practice" for managing your resources if you ever write in other languages where it matters more. So it's not "useless and superfluous", and it might be useful for people still using older versions of Windows that maybe don't handle it as well. As Nine said, you're saving microseconds, but there is a small gain in opening the DLL yourself, around 9-10%. Unless you're making literally millions of calls though, it's not going to make much of a difference. Here's a test I did for 1,000,000 runs with kernel32 calling GetTickCount64: +———————————————+—————————————————+———————————————+——————————————+—————————————+ | Function Name | Time Taken (ms) | Avg Time (ms) | Std Dev (ms) | Faster By % | +———————————————+—————————————————+———————————————+——————————————+—————————————+ | DllCall | 8179.74 | 0.0082 | 0.0056 | 0.00 | +| DllCall(Open) | 7444.30 | 0.0074 | 0.0032 | 8.99 | +———————————————+—————————————————+———————————————+——————————————+—————————————+ | Total time | 15624.03 | | | | +———————————————+—————————————————+———————————————+——————————————+—————————————+ So, is it worth doing? Yeah, why not? Is it necessary if you open a DLL to close it? Nah, AutoIt and/or Windows will manage that pretty well for you. Is not doing it hurting you? Nah.
    1 point
  9. There are two updates available. The WinHTTP one shouldn't be ignored. Probably because you are running the 32 bit version of geckodriver. You can resolve by either -- switching to 64 bit version of geckodriver Add the "binary" option to your capabilities string (you should be able to find examples of this on the forum / wiki). P.S. Upgrading to the newest UDF release won't fix this issue, but it should give better error logging that helps with diagnosing issues such as this.
    1 point
  10. I have updated the current production installer with the newer version of SciTEConfig.au3 which will do these steps when there is a different Username in the parent process tree: Copy %LOCALAPPDATA%\AutoIt v3 directory from the Admin username to the original user. Update the "HKEY_USERS\SID\Environment" key "SCITE_USERHOME" for the SID of the original Username. The Environment is also updated so it should work without a restart of Explorer or Logout&Login Additional install_user.log will be generated in the SciTE directory with info about the above. Update Tidy to avoid the initial SciTEConsole Debug messages hanging it for a while. Please give that a try to see if that works and let me know, so I can implement this for the next release. Jos
    1 point
  11. Uploaded an updated ZIP file with these changes: Restored/incorporated the proper.case functionality again into the new autocomplete functions.It will now "proper.case" any known Function/UDF/Keyword/Macro/Directive. Macro's will now also be shown in the AutoComplete dropdown box Jos
    1 point
  12. I'm trying to figure out why the data is structured just this way. You create an incredibly nested structure (948 nested levels!). But I don't know why it wouldn't be enough to create a simple array with the values and apply the mapping function to each of these elements. The result would be the same, but much easier to understand and better performing. Can you give me a hint if I am missing something important? I have also dealt with this topic before. The result are some functions, which then are included in my ArrayPlus-UDF. In order to produce the same result as yours, a single line of code would suffice with the UDF: #include "ArrayPlus.au3" ; create Array with initial values 948..0 and map a user defined function to these values: $a = _ArrayCreate("948:0:-1", "$A*$A + $A") ; display the result: _ArrayDisplay($a, "result") Or if it should be more like your setup with an explicit map function then like this: #include "ArrayPlus.au3" ; create array with values 948..0 $a = _ArrayCreate("0:948") ; map a function to every element of the array _ArrayMap($a, sumSelfAndSquare) ; display the result _ArrayDisplay($a, "result") func sumSelfAndSquare($x) return $x*$x + $x endfunc
    1 point
  13. I'm finding whatever I can to procrastinate finishing and releasing my own project, so here's a method very very close to what you've provided, but doing it in a much more (in my opinion) straight-forward way: Global $hTimer = TimerInit() Global $a = Pack(948) ConsoleWrite('- Pack(948): ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF & @CRLF) $hTimer = TimerInit() Global $b = Map("sumSelfAndSquare", $a) ConsoleWrite('- Map("sumSelfAndSquare", $a): ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF & @CRLF) $hTimer = TimerInit() Global $b = Map(sumSelfAndSquare, $a) ConsoleWrite('- Map(sumSelfAndSquare, $a): ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF & @CRLF) $hTimer = TimerInit() ConsoleWrite(Unpack($a) & @CRLF & @CRLF) ConsoleWrite('- Unpack($a): ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF & @CRLF) $hTimer = TimerInit() ConsoleWrite(Unpack($b) & @CRLF & @CRLF) ConsoleWrite('- Unpack($b): ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF & @CRLF) Func Map($sFunction, $aArray) Local $sResult[UBound($aArray)] For $i = 0 To UBound($aArray) - 1 If IsFunc($sFunction) Then $sResult[$i] = $sFunction($aArray[$i]) Else $sResult[$i] = Call($sFunction, $aArray[$i]) EndIf Next Return $sResult EndFunc ;==>Map Func Unpack($aArray) Local $sResult = "" For $i = 0 To UBound($aArray) - 1 $sResult &= $aArray[$i] If $i < UBound($aArray) - 1 Then $sResult &= " , " Next Return $sResult EndFunc ;==>Unpack Func Pack($iIndex) Local $aArray[$iIndex] For $i = 0 To $iIndex - 1 $aArray[$i] = $i Next Return $aArray EndFunc ;==>Pack Func sumSelfAndSquare($x) Return $x * $x + $x EndFunc ;==>sumSelfAndSquare No recursion with a nest of arrays, otherwise I think that it adopts to what you were showcasing. This just breaks my brain less.
    1 point
  14. I think this is pretty cool, took me a while to get my head around it, and I assume that you meant to post it in the example scripts section, unless you have a question? I also changed the names of some params to better understand it personally, and while it's neat, I don't see a use for it myself. Here's my updates, and comparison to a 'normal' way of doing it in AutoIt: Global $hTimer = TimerInit() #Region Haskell-like Global $a = pack(948) ConsoleWrite('pack(948): ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF) $hTimer = TimerInit() Global $b = map(sumSelfAndSquare, $a) ConsoleWrite('map(sumSelfAndSquare, $a): ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF) $hTimer = TimerInit() ConsoleWrite('unpack($a): ' & unpack($a) & ': ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF & @CRLF) $hTimer = TimerInit() ConsoleWrite('unpack($b): ' & unpack($b) & ': ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF & @CRLF) #EndRegion Haskell-like #Region Normal array and loop $hTimer = TimerInit() Global $aPack[948] ConsoleWrite('$aPack[948]: ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF) $hTimer = TimerInit() For $iIndex = 0 To UBound($aPack) - 1 $aPack[$iIndex] = sumSelfAndSquare($iIndex) Next ConsoleWrite('$aPack = sumSelfAndSquare: ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF) $hTimer = TimerInit() For $iIndex = 0 To UBound($aPack) - 1 ConsoleWrite($aPack[$iIndex] & (($iIndex = UBound($aPack) - 1) ? '' : ' , ')) Next ConsoleWrite(@CRLF) ConsoleWrite('$aPack logging: ' & Round(TimerDiff($hTimer), 2) & ' ms' & @CRLF) #EndRegion Normal array and loop Func map($sFunc, $aPackedData) Return IsArray($aPackedData[0]) ? __mapContinue($sFunc, $aPackedData) : __mapLast($sFunc, $aPackedData) EndFunc ;==>map Func __mapContinue($sFunc, $aPackedData) Local $aArray = [map($sFunc, $aPackedData[0]), $sFunc($aPackedData[1])] Return $aArray EndFunc ;==>__mapContinue Func __mapLast($sFunc, $aPackedData) Local $aArray = [$sFunc($aPackedData[0])] Return $aArray EndFunc ;==>__mapLast Func unpack($aArray) Return IsArray($aArray[0]) ? $aArray[1] & ' , ' & unpack($aArray[0]) : $aArray[0] EndFunc ;==>unpack Func pack($iIndex) If $iIndex > 0 Then Local $a = [pack($iIndex - 1), $iIndex] ElseIf $iIndex = 0 Then Local $a = [$iIndex] Else Local $a = [1] Return SetError(1, $iIndex, $a) EndIf Return $a EndFunc ;==>pack Func sumSelfAndSquare($x) Return $x * $x + $x EndFunc ;==>sumSelfAndSquare For me it took around ~30ms for the Haskell like code (excluding unpacking $a), and ~6.7ms for the normal array approach. I can't personally see any use for implementing this, considering that it took me a while to understand what's happening, it just wouldn't be worth it to me to add this complexity for no benefit that I can see. Please let me know if I'm missing some awesome use-case for this. Otherwise again I do think this is neat. And kudos to you for implementing it with AutoIt.
    1 point
  15. That is obviously not an accurate representation of your cURL command line -- at least I hope it isn't. It doesn't even have a target API URL. So without an accurate representation (even if you have to redact the URL), how is anyone suppose to know if it is correct. Your initial example is setting the "Accept" header. Why aren't you setting the "Content-Type" header also. The "Content-Type" header, which should be "application/json", says that the request data should be interpreted as JSON. It may not be required, but it is still good practice to define the content type. Your Run(), at least as it is shown, does not require you to prepend @comspec. If you already have valid JSON in a file, then just use cURL's @ syntax to have it read in the file. (see example below) If you need more information about cURL parameters, you can find them in the online cURL documentation. You haven't provided a complete script. So, again, there's no way to know what other issues you may have in your script. The example below, sends a POST request to the postman echo server. The echo server sends back information about your request as it was received by the server (including the request headers) The "temp.json" file that is referenced contains your JSON dataset. As you can see in the echo server's response, the cURL command successfully sent the request. The "data" field shows the POST data that was received. The "JSON" field shows JSON because the Content-Type header was sent so it knew that the data was JSON. Also in the example's command line you will see a "--json" parameter. You can use that parameter if you are using cURL version 7.82.0 or newer. It's a shortcut that does 3 things: passes the json data or file, sets the "Content-Type" header to application/json, and sets the "Accept" header to application/json. You should be able to adapt the example to fit your needs. Example: #include <Constants.au3> Const $CURL_EXE = "c:\utils\curl\curl64.exe" ;Modify path as needed Const $JSON_FILE = "temp.json" ;Modify path as needed Const $API_URL = "https://postman-echo.com/post" ;Modify URL as needed example() Func example() Local $sCmdLine = "" Local $iPid = 0 ;Build command line $sCmdLine = StringFormat('"%s" -s --json @"%s" "%s"', $CURL_EXE, $JSON_FILE, $API_URL) ConsoleWrite("Cmd Line = " & $sCmdLine & @CRLF) ;Execute command line $iPid = Run($sCmdLine, "", @SW_HIDE, $STDERR_MERGED) If Not $iPid Then Exit MsgBox($MB_ICONERROR, "Run Error", "Check to make sure your command line is valid.") ;Wait for the process to close ProcessWaitClose($iPid) ;Display command output ConsoleWrite(@CRLF & "Response:" & @CRLF) ConsoleWrite(StdoutRead($iPid) & @CRLF) EndFunc Console output: Cmd Line = "c:\utils\curl\curl64.exe" -s --json @"temp.json" "https://postman-echo.com/post" Response: { "args": {}, "data": { "documentTypes": [ "=EMAIL=" ], "query": { "type": "AND", "constraints": [ { "type": "FIELD_COMPARISON", "field": "SENT_DATE", "operator": "RANGE", "range": { "min": "2023-03-01T00:00:00", "max": "2023-03-17T23:59:59" } }, { "type": "AND", "constraints": [ { "type": "FIELD_COMPARISON", "customField": "DOC_TYPE", "field": "CUSTOM_SORTABLE_STRING", "value": "=EMAIL=", "operator": "EQUAL_TO" }, { "type": "FIELD_COMPARISON", "customField": "CONTENT-TYPE", "field": "CUSTOM_SORTABLE_STRING", "value": "SM", "operator": "MATCHES" } ] } ] }, "queryOptions": { "source": "LEGACY", "type": "COUNT", "suppressQueryTranslationWarning": true }, "resultColumns": [] }, "files": {}, "form": {}, "headers": { "x-forwarded-proto": "https", "x-forwarded-port": "443", "host": "postman-echo.com", "x-amzn-trace-id": "Root=1-6422223a-2c910a151f0d3bd901a5f748", "content-length": "1170", "user-agent": "curl/8.0.1", "content-type": "application/json", "accept": "application/json" }, "json": { "documentTypes": [ "=EMAIL=" ], "query": { "type": "AND", "constraints": [ { "type": "FIELD_COMPARISON", "field": "SENT_DATE", "operator": "RANGE", "range": { "min": "2023-03-01T00:00:00", "max": "2023-03-17T23:59:59" } }, { "type": "AND", "constraints": [ { "type": "FIELD_COMPARISON", "customField": "DOC_TYPE", "field": "CUSTOM_SORTABLE_STRING", "value": "=EMAIL=", "operator": "EQUAL_TO" }, { "type": "FIELD_COMPARISON", "customField": "CONTENT-TYPE", "field": "CUSTOM_SORTABLE_STRING", "value": "SM", "operator": "MATCHES" } ] } ] }, "queryOptions": { "source": "LEGACY", "type": "COUNT", "suppressQueryTranslationWarning": true }, "resultColumns": [] }, "url": "https://postman-echo.com/post" }
    1 point
  16. Comment: 'System crash', 'stack overflow', 'unable to obtain handles', 'memory exhausted' error codes is what happens if you create new handles and never close them, especially in re-entrant loops. How do I know? Grins (or cringes) Wait till you try and debug DLLhell, where there are different versions of exactly the same named DLL scattered across your system, all with similar internal function names but different functionality, and the order in which they are encountered by your software determines how far your system remains stable before it crashes and burns. Yes, I'm looking at you Microsoft, Oracle, Nero, Java and Adobe. Hard and fast Rulez (from experience): If you open it, close it. If it is up, put it down when you flush. Keep subroutines and calls open for as short a time as possible. Be aware of local vs global variables. Don't be lazy with variable naming - 'temp' is often found to be a global variable. Read the doco. Test for return codes. Check for version levels during API calls. Always include a 'or else' clause. Make your error codes meaningful and easy to document. Declare your global variables at the top separately. Pseudocode is not wasted code. Planning is not an overhead. Use the right tool for the job. COBOL is not a good environment to write a keylogger package, and Excel is not a good covid data tracker! All developers speak profanity fluently. It is the first and most developed language universally. Getting your code to compile the first time is nearly as good as sex - nearly!
    1 point
  17. Thanks to all of you. This forum is incredible because everybody likes to help. Sharing all together solutions to issues is what makes this forum special.
    1 point
  18. The _ProcessListProperties() function has been floating around General Help and Support long enough. This is it's new home. This function lists several properties of all processes (default), selected processes by name, or a single process by PID. ===> Important bug note: The SwbemRefresher object has a Microsoft bug that causes a memory leak when called repeatedly. Until a fix is found from Microsoft, don't use _ProcessListProperties() in a tight loop. <=== Change Log: 05/05/2008 -- v1.0.0 -- First version placed in Example Scripts 05/07/2008 -- v1.0.1 -- Added the calling command line at [n][9] 06/10/2008 -- v2.0.0 -- Removed use of ProcessList() so remote access could work 06/12/2008 -- v2.0.1 -- Added geeky RegExp for WMI date conversion by weaponx 07/02/2008 -- v2.0.2 -- Fixed find by PID or Name, which was broken by removing ProcessList() usage 09/17/2008 -- v2.0.3 -- Added Debug (SeDebugPrivilege) to WMI call to retrieve fuller results 12/15/2008 -- v2.0.3 -- No change to function, cleaned up demo and added COM error handler to it12/01/2009 -- v2.0.4 -- Fixed check for null $Process so '0' could be used (System Idle Process) Information is returned in a 2D array similar to the native ProcessList(), in fact the UDF uses ProcessList() internally. This is the structure of the array: [0][0] - Number of processes listed (can be 0 if no matches found) [1][0] - 1st process name [1][1] - 1st process PID [1][2] - 1st process Parent PID [1][3] - 1st process owner [1][4] - 1st process priority (0 = low, 31 = high) [1][5] - 1st process executable path [1][6] - 1st process CPU usage [1][7] - 1st process memory usage [1][8] - 1st process creation date/time = "MM/DD/YYY hh:mm:ss" [1][9] - 1st process command line string ... [n][0] thru [n][9] - last process properties Here is the function, with a running demo script: #include <Array.au3>; Only for _ArrayDisplay() ; Install a custom error handler Global $oMyError = ObjEvent("AutoIt.Error","MyErrFunc"), $f_COMError = False ; Globals Global $avRET, $iPID ; Demonstrate listing all processes $avRET = _ProcessListProperties() _ArrayDisplay($avRET, "All Processes") ; Demonstrate listing by name $avRET = _ProcessListProperties("svchost.exe") _ArrayDisplay($avRET, "By name: 'svchost.exe'") ; Demonstrate listing by PID (integer) $iPID = ProcessExists("svchost.exe") $avRET = _ProcessListProperties($iPID) _ArrayDisplay($avRET, "By int PID: " & $iPID) ; Demonstrate listing by PID (numeric string) $iPID = String($iPID) $avRET = _ProcessListProperties($iPID) _ArrayDisplay($avRET, "By string PID: " & $iPID) ; Demonstrate not found $avRET = _ProcessListProperties("NoSuchProcess.exe") _ArrayDisplay($avRET, "Not found: 'NoSuchProcess.exe'") ; This is my custom error handler Func MyErrFunc() Local $HexNumber=hex($oMyError.number,8) Msgbox(0,"","We intercepted a COM Error !" & @CRLF & _ "Number is: " & $HexNumber & @CRLF & _ "WinDescription is: " & $oMyError.windescription & @CRLF & _ "Source is: " & $oMyError.source & @CRLF & _ "ScriptLine is: " & $oMyError.scriptline) $f_COMError = True; something to check for when this function returns Endfunc ;=============================================================================== ; Function Name: _ProcessListProperties() ; Description: Get various properties of a process, or all processes ; Call With: _ProcessListProperties( [$Process [, $sComputer]] ) ; Parameter(s): (optional) $Process - PID or name of a process, default is "" (all) ; (optional) $sComputer - remote computer to get list from, default is local ; Requirement(s): AutoIt v3.2.4.9+ ; Return Value(s): On Success - Returns a 2D array of processes, as in ProcessList() ; with additional columns added: ; [0][0] - Number of processes listed (can be 0 if no matches found) ; [1][0] - 1st process name ; [1][1] - 1st process PID ; [1][2] - 1st process Parent PID ; [1][3] - 1st process owner ; [1][4] - 1st process priority (0 = low, 31 = high) ; [1][5] - 1st process executable path ; [1][6] - 1st process CPU usage ; [1][7] - 1st process memory usage ; [1][8] - 1st process creation date/time = "MM/DD/YYY hh:mm:ss" (hh = 00 to 23) ; [1][9] - 1st process command line string ; ... ; [n][0] thru [n][9] - last process properties ; On Failure: Returns array with [0][0] = 0 and sets @Error to non-zero (see code below) ; Author(s): PsaltyDS at http://www.autoitscript.com/forum ; Date/Version: 12/01/2009 -- v2.0.4 ; Notes: If an integer PID or string process name is provided and no match is found, ; then [0][0] = 0 and @error = 0 (not treated as an error, same as ProcessList) ; This function requires admin permissions to the target computer. ; All properties come from the Win32_Process class in WMI. ; To get time-base properties (CPU and Memory usage), a 100ms SWbemRefresher is used. ;=============================================================================== Func _ProcessListProperties($Process = "", $sComputer = ".") Local $sUserName, $sMsg, $sUserDomain, $avProcs, $dtmDate Local $avProcs[1][2] = [[0, ""]], $n = 1 ; Convert PID if passed as string If StringIsInt($Process) Then $Process = Int($Process) ; Connect to WMI and get process objects $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy, (Debug)}!\\" & $sComputer & "\root\cimv2") If IsObj($oWMI) Then ; Get collection processes from Win32_Process If $Process == "" Then ; Get all $colProcs = $oWMI.ExecQuery("select * from win32_process") ElseIf IsInt($Process) Then ; Get by PID $colProcs = $oWMI.ExecQuery("select * from win32_process where ProcessId = " & $Process) Else ; Get by Name $colProcs = $oWMI.ExecQuery("select * from win32_process where Name = '" & $Process & "'") EndIf If IsObj($colProcs) Then ; Return for no matches If $colProcs.count = 0 Then Return $avProcs ; Size the array ReDim $avProcs[$colProcs.count + 1][10] $avProcs[0][0] = UBound($avProcs) - 1 ; For each process... For $oProc In $colProcs ; [n][0] = Process name $avProcs[$n][0] = $oProc.name ; [n][1] = Process PID $avProcs[$n][1] = $oProc.ProcessId ; [n][2] = Parent PID $avProcs[$n][2] = $oProc.ParentProcessId ; [n][3] = Owner If $oProc.GetOwner($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName ; [n][4] = Priority $avProcs[$n][4] = $oProc.Priority ; [n][5] = Executable path $avProcs[$n][5] = $oProc.ExecutablePath ; [n][8] = Creation date/time $dtmDate = $oProc.CreationDate If $dtmDate <> "" Then ; Back referencing RegExp pattern from weaponx Local $sRegExpPatt = "\A(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(?:.*)" $dtmDate = StringRegExpReplace($dtmDate, $sRegExpPatt, "$2/$3/$1 $4:$5:$6") EndIf $avProcs[$n][8] = $dtmDate ; [n][9] = Command line string $avProcs[$n][9] = $oProc.CommandLine ; increment index $n += 1 Next Else SetError(2); Error getting process collection from WMI EndIf ; release the collection object $colProcs = 0 ; Get collection of all processes from Win32_PerfFormattedData_PerfProc_Process ; Have to use an SWbemRefresher to pull the collection, or all Perf data will be zeros Local $oRefresher = ObjCreate("WbemScripting.SWbemRefresher") $colProcs = $oRefresher.AddEnum($oWMI, "Win32_PerfFormattedData_PerfProc_Process" ).objectSet $oRefresher.Refresh ; Time delay before calling refresher Local $iTime = TimerInit() Do Sleep(20) Until TimerDiff($iTime) >= 100 $oRefresher.Refresh ; Get PerfProc data For $oProc In $colProcs ; Find it in the array For $n = 1 To $avProcs[0][0] If $avProcs[$n][1] = $oProc.IDProcess Then ; [n][6] = CPU usage $avProcs[$n][6] = $oProc.PercentProcessorTime ; [n][7] = memory usage $avProcs[$n][7] = $oProc.WorkingSet ExitLoop EndIf Next Next Else SetError(1); Error connecting to WMI EndIf ; Return array Return $avProcs EndFunc ;==>_ProcessListProperties Constructive criticism welcome.
    1 point
  19. Process CPU Usage Trackers As yet another alternative to the Performance Counters UDF, I've created this UDF to allow easy tracking of one or more processes's CPU usage. While this has obviously been done before, I haven't seen it done the way I've created it. Basically, just as the Performance Counters had Process Counter objects, so this too has Process Usage trackers. They are relatively simple to use, and require very little interaction other than invoking the functions. To create a new tracker object, call one of these: _ProcessUsageTracker_Create() ; Single process tracker _ProcessesUsageTracker_Create() ; Multiple processes tracker The multiple-process tracker requires addition of processes, which can be done one of 2 ways: _ProcessesUsageTracker_Add() ; add a single process _ProcessesUsageTracker_AddMultiple() ; multiple processes in a ProcessList-style array After the usage tracker object has been created, stats can be collected via one of two calls: _ProcessUsageTracker_GetUsage() ; single process - returns a percentage _ProcessesUsageTracker_GetUsage() ; multiple Processes - returns an array of %'s Basically the main loop of the program can be filled with 'GetUsage' calls without juggling anything around. If a process dies out, an @error code will be returned in the single-process version. The multiple-process tracker version however lets you retain dead processes in the list although their process handles will be closed. These can be alternatively cleared up on each call to 'GetUsage' (setting $bRemoveDead to True), or you can opt to clean them up with the following call: _ProcessesUsageTracker_RemoveDead() ; Removes any dead processes from the tracker object Finally, to destroy the trackers and close handles, just call the appropriate function: _ProcessUsageTracker_Destroy() _ProcessesUsageTracker_Destroy() That's about it. More info is in the headers. Here's an example of a single process cpu usage tracker: ; ======================================================================================================== ; <Process_CPUUsageExample.au3> ; ; Example usage of <Process_CPUUsage.au3> ; ; Author: Ascend4nt ; ======================================================================================================== #include "Process_CPUUsage.au3" ; -------------------- HOTKEY FUNCTION & VARIABLE -------------------- Global $bHotKeyPressed=False Func _EscPressed() $bHotKeyPressed=True EndFunc ; -------------------- MAIN PROGRAM CODE -------------------- HotKeySet("{Esc}", "_EscPressed") Local $hSplash, $sSplashText Local $sProcess, $aProcUsage, $fUsage ; Regular Process: ;~ $sProcess = "firefox.exe" ;~ $sProcess = "sp2004.exe" ; Stress Prime 2004 ; Protected Process (opens a different way): ;~ $sProcess = "audiodg.exe" ; Processes Requiring elevated privilege (will fail even with limited access rights): ;~ $sProcess = "CTAudSvc.exe" $sProcess = InputBox("Enter Process Name", "Process Name:", "", "", 320, 140) If @error Or $sProcess = "" Then Exit $aProcUsage = _ProcessUsageTracker_Create($sProcess) If @error Then Exit ConsoleWrite("Error calling _ProcessUsageTracker_Create(): " & @error & ", @extended = " & @extended & @CRLF) Sleep(250) $hSplash=SplashTextOn("Process CPU Usage Information", "", 360, 20 + 60, Default, Default, 16, Default, 12) ; Start loop Do $sSplashText="" $fUsage = _ProcessUsageTracker_GetUsage($aProcUsage) If @error Then ConsoleWrite("Error from _ProcessUsageTracker_GetUsage(): " & @error & ", @extended = " &@extended & @CRLF) ExitLoop EndIf $sSplashText &= "'"&$sProcess&"' CPU usage: " & $fUsage & " %" & @CRLF $sSplashText &= @CRLF & "[Esc] exits" ControlSetText($hSplash, "", "[CLASS:Static; INSTANCE:1]", $sSplashText) Sleep(500) Until $bHotKeyPressed _ProcessUsageTracker_Destroy($aProcUsage) _ Multiple processes example, which is best used with something like 'chrome' which spawns a number of processes with the same name: ; ======================================================================================================== ; <Processes_CPUUsageExample.au3> ; ; Example usage of <Processes_CPUUsage.au3> ; ; Author: Ascend4nt ; ======================================================================================================== #include "Processes_CPUUsage.au3" ; -------------------- HOTKEY FUNCTION & VARIABLE -------------------- Global $bHotKeyPressed=False Func _EscPressed() $bHotKeyPressed=True EndFunc ; -------------------- MAIN PROGRAM CODE -------------------- HotKeySet("{Esc}", "_EscPressed") Local $hSplash, $sSplashText Local $sProcess, $aProcList, $aProcUsage, $aPercents, $nPercents ; Regular Process: ;~ $sProcess = "firefox.exe" ;~ $sProcess = "sp2004.exe" ; Stress Prime 2004 ; Protected Process (opens a different way): ;~ $sProcess = "audiodg.exe" ; Processes Requiring elevated privilege (will fail even with limited access rights): ;~ $sProcess = "CTAudSvc.exe" $sProcess = InputBox("Enter Process Name", "Process Name:", "", "", 320, 140) If @error Or $sProcess = "" Then Exit $aProcUsage = _ProcessesUsageTracker_Create() _ProcessesUsageTracker_Add($aProcUsage, "sp2004.exe") _ProcessesUsageTracker_Add($aProcUsage, "CPUStabTest.exe") $aProcList = ProcessList("chrome.exe") _ProcessesUsageTracker_AddMultiple($aProcUsage, $aProcList) _ProcessesUsageTracker_Add($aProcUsage, $sProcess) _ProcessesUsageTracker_Add($aProcUsage, "audiodg.exe") Sleep(250) $hSplash=SplashTextOn("Process CPU Usage Information", "", 380, 24 + 15*2 + $aProcUsage[0][0]*15, Default, Default, 16+4, "Lucida Console", 11) ; Start loop Do ; DEBUG: Interrupt to allow multiple process termination ;MsgBox(0, "Next usage", "Next usage time..") $sSplashText="" $aPercents = _ProcessesUsageTracker_GetUsage($aProcUsage, True) ; True = Remove dead $nPercents = @extended If @error Then ConsoleWrite("Error from _ProcessesUsageTracker_GetUsage(): " & @error & ", @extended = " &@extended & @CRLF) ExitLoop EndIf For $i = 0 To $nPercents - 1 $sSplashText &= "'"&$aProcUsage[$i+1][0]&"' [PID #"&$aProcUsage[$i+1][1]&"] CPU usage: " & $aPercents[$i] & " %" & @CRLF Next $sSplashText &= @CRLF & "[Esc] exits" ControlSetText($hSplash, "", "[CLASS:Static; INSTANCE:1]", $sSplashText) Sleep(500) Until $bHotKeyPressed _ProcessesUsageTracker_Destroy($aProcUsage) ProcessCPUUsage.zip
    1 point
×
×
  • Create New...