Leaderboard
Popular Content
Showing content with the highest reputation on 02/06/2018 in all areas
-
Hey guys.. finally got it working! From 23s to 1s for activation #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7 #include "UIAWrappers.au3" Local $oButton Local $program = "McCampbell Omega_Me - [ODBC;DRIVER=SQL Server Native Client 10.0;SERVER=tcp:MAI-SQL\MAI_BACKEND;UID=huan;PWD=;Trusted_Connection=Yes;APP=Microsoft Offi]" #forceref $oButton #AutoIt3Wrapper_UseX64=Y ;Should be used for stuff like tagpoint having right struct etc. when running on a 64 bits os Local $omega = _UIA_getFirstObjectOfElement($UIA_oDesktop, $program, $treescope_children) $oButton = _UIA_getFirstObjectOfElement($omega, "name:=Analytical", $treescope_subtree) local $oLegacyP=_UIA_getPattern($oButton,$UIA_LegacyIAccessiblePatternId) $oLegacyP.dodefaultaction()2 points
-
Features: Create modern looking borderless and resizable GUIs with control buttons (Close,Maximize/Restore,Minimize, Fullscreen, Menu) True borderless, resizeable GUI with full support for aerosnap etc. Many color schemes/themes included. See MetroThemes.au3 for more details. 3 type of Windows 8/10 style buttons. Modern checkboxes, radios, toggles and progressbar. All buttons, checkboxes etc. have hover effects! Windows 10 style modern MsgBox. Windows 10/Android style menu that slides in from left. Windows 10 style right click menu Credits: @UEZ, for the function to create buttons with text using GDIPlus. @binhnx for his SSCtrlHover UDF Changelog: Download UDF with example:1 point
-
The collection of examples in .NET Common Language Runtime (CLR) Framework shows that there are virtually no limits to the possibilities that the usage of .NET Framework and .NET code in AutoIt opens up for. One possibility which certainly is very interesting is the possibility of using C# and VB code in AutoIt. That is, to create, compile and execute C# and VB source code directly through an AutoIt script without the need for any external tools at all, eg. an integrated development environment (IDE) program or similar. You can even create a .NET assembly dll-file with your C# or VB code that you can simply load and execute. Why is it interesting to execute C# or VB code in an AutoIt script? It's interesting because C# and VB code is executed as compiled code and not as interpreted code like AutoIt code. Compiled code is very fast compared to interpreted code. In AutoIt and all other interpreted languages probably 99% or more of the total execution time is spend by the code interpretor to interpret the code lines, while only 1% or less of the total execution time is spend by executing the actual code. Compiled code is directly executable without the need for a code interpretor. That's the reason why compiled code is so much faster than interpreted code. Using C# and VB code in AutoIt is interesting because it can be used to performance optimize the AutoIt code. There may be many other good reasons for using C# and VB code in AutoIt, but here the focus is on code optimization. In the help and support forums you can regularly find questions related to this topic. You can find many examples where assembler code is used in connection with performance optimization. Recently, there has been some interest in FreeBASIC. Code optimization is clearly a topic that has some interest. How difficult is writing C# and VB code compared to assembler and FreeBASIC code? It's certainly much easier and faster than writing assembler code. Because you can do everything through AutoIt without the need for an IDE, it's probably also easier than FreeBASIC. As usually you get nothing for free. The cost is that there is some overhead associated with executing compiled code. You must load and start the code. You need methods to move data back and forth between the AutoIt code and the compiled code. You'll not see that all compiled code is 100 times faster than AutoIt code. Somewhere between 10 and 100 times faster is realistic depending on the complexity of the code. And probably also only code running in loops is interesting and preferably a lot of loops. How C# and VB code can be used in AutoIt through .NET Framework is what this example is about. The rest of first post is a review of introductory C# and VB examples. The purpose of the examples is to make it easier to use C# and VB code in AutoIt. They show how to do some of the basic things in C#/VB that you can do in AutoIt. They focus on topics that are relevant when both AutoIt and C#/VB code is involved. Eg. how to pass variables or arrays back and forth between AutoIt and C#/VB code. The examples are not meant to be a regular C#/VB tutorial. C# and VB Guides in Microsoft .NET Documentation is a good place to find information about C# and VB code. Dot Net Perls example pages have some nice examples. To avoid first post being too long, three posts are reserved for topics that will be presented in the coming weeks. DotNet.au3 UDF DotNet.au3 UDF to access .NET Framework from AutoIt is used to access the .NET Framework. But you do not at all need a detailed knowledge of the code in DotNet.au3 to use C#/VB code in AutoIt. The UDF is stored as DotNetAll.au3 in Includes\ in the zip-file in bottom of post. Includes\ only contains this file. Introductory C# and VB examples The code in the examples below is VB code. But the zip-file in bottom of post contains both C# and VB versions of the examples. Code templates This is the vb and au3 code templates that's used in all of the examples. TemplateVB.vb (TemplateVB-a.vb is provided with comments): Imports System Class Au3Class Public Sub MyMethod() Console.WriteLine( "Hello world from VB!" ) End Sub End Class Note that Console.WriteLine writes output to SciTE console. TemplateVB.au3: #include "..\..\..\Includes\DotNetAll.au3" Opt( "MustDeclareVars", 1 ) Example() Func Example() Local $oNetCode = DotNet_LoadVBcode( FileRead( "TemplateVB.vb" ), "System.dll" ) Local $oAu3Class = DotNet_CreateObject( $oNetCode, "Au3Class" ) $oAu3Class.MyMethod() EndFunc Usually, 2 code lines are sufficient to make .NET code available in AutoIt. DotNet_LoadVBcode() compiles the VB code, creates the .NET code in memory, loads the code into the default domain and returns a .NET code object which is a reference to the .NET code. DotNet_CreateObject() takes the .NET code object and a class name as input parameters and creates an object from the class. See DotNet.au3 UDF. Now the sub procedure MyMethod in the VB code can be executed as an object method. Most examples contains just a few code lines like the templates. I don't want to review all examples, but to get an idea of what this is about, here's a list of the top level folders in the zip-file: Code templates Introductory topics Comments Comment block Line continuation ConsoleWrite MessageBox Public keyword Multiple methods Subs, functions Global variable Error handling Missing DLL-file Imports, using CS-VB mismatch Code typing errors Set @error macro Passing variables Passing 1D arrays Passing 2D arrays Simple examples Prime numbers Create DLL Prime numbers So far, there is only one example with more than just a few code lines. This is an example of calculating prime numbers. This example is also used to show how to create a .NET assembly dll-file. These two examples are reviewed with more details below. Prime numbers The example calculates a certain number of prime numbers and returns the prime numbers as a 1D array. It shows how to pass an AutoIt variable (number of prime numbers) to the C#/VB code and how to return a 1D array of integers (the prime numbers) from the C#/VB code to AutoIt. Especially arrays are interesting in relation to compiled code. This is Microsoft documentation for VB arrays and C# arrays. Design considerations If you want to create a UDF that uses advanced techniques such as compiled code, and you want to make it available to other members, you should consider the design. Consider how the code should be designed to be attractive to other members. You should probably not design the code so other members will need to execute .NET code, create objects, and call object methods in their own code. This should be done in a function in the UDF so that a user can simply call an easy-to-use AutoIt function in the usual way. AutoIt and VB code There are three versions of the example. A pure AutoIt version in the au3-folder, an AutoIt/VB version in the VB-folder and an AutoIt/C# version in the CS-folder. The pure AutoIt and the AutoIt/VB versions are reviewed below. AutoIt code in au3\CalcPrimes.au3. This is the pure AutoIt UDF to calculate primes: #include-once Func CalcPrimes( $nPrimes ) Local $aPrimes[$nPrimes], $iPrime = 2, $iPrimes = 0 If $nPrimes <= 100 Then ConsoleWrite( $iPrime & @CRLF ) ; Store first prime $aPrimes[$iPrimes] = $iPrime $iPrimes += 1 $iPrime += 1 ; Loop to calculate primes While $iPrimes < $nPrimes For $i = 0 To $iPrimes - 1 If Mod( $iPrime, $aPrimes[$i] ) = 0 Then ExitLoop Next If $i = $iPrimes Then If $nPrimes <= 100 Then ConsoleWrite( $iPrime & @CRLF ) $aPrimes[$iPrimes] = $iPrime $iPrimes += 1 EndIf $iPrime += 1 WEnd Return $aPrimes EndFunc Note the similarity between the AutoIt code above and the VB code below. If you can write the AutoIt code you can also write the VB code. VB code in VB\CalcPrimesVB.vb to calculate primes: Imports System Class PrimesClass Public Function CalcPrimes( nPrimes As Integer ) As Integer() Dim aPrimes(nPrimes-1) As Integer, iPrime As Integer = 2, iPrimes As Integer = 0, i As Integer If nPrimes <= 100 Then Console.WriteLine( iPrime ) 'Store first prime aPrimes(iPrimes) = iPrime iPrimes += 1 iPrime += 1 'Loop to calculate primes While iPrimes < nPrimes For i = 0 To iPrimes - 1 If iPrime Mod aPrimes(i) = 0 Then Exit For Next If i = iPrimes Then If nPrimes <= 100 Then Console.WriteLine( iPrime ) aPrimes(iPrimes) = iPrime iPrimes += 1 End If iPrime += 1 End While Return aPrimes End Function End Class AutoIt code in VB\CalcPrimesVB.au3. This is the AutoIt/VB UDF to calculate primes. #include-once #include "..\..\..\..\..\Includes\DotNetAll.au3" Func CalcPrimesVBInit() CalcPrimesVB( 0 ) EndFunc Func CalcPrimesVB( $nPrimes ) Static $oNetCode = 0, $oPrimesClass = 0 If $nPrimes = 0 Or $oNetCode = 0 Then ; Compile and load VB code, create PrimesClass object $oNetCode = DotNet_LoadVBcode( FileRead( "CalcPrimesVB.vb" ), "System.dll" ) $oPrimesClass = DotNet_CreateObject( $oNetCode, "PrimesClass" ) If $nPrimes = 0 Then Return EndIf ; Execute CalcPrimes method and return 1D array of primes Return $oPrimesClass.CalcPrimes( $nPrimes ) EndFunc Note the initialization code in CalcPrimesVB() where the VB code is compiled and loaded and the $oPrimesClass object is created. If the user forgets to call CalcPrimesVBInit() it'll work anyway. Examples with pure AutoIt code in au3\Examples.au3. This is user code: #include <Array.au3> #include "CalcPrimes.au3" Opt( "MustDeclareVars", 1 ) Examples() Func Examples() ShowPrimes( 10 ) ; Used under development ShowPrimes( 1000 ) ; 400 milliseconds ShowPrimes( 5000 ) ; 8 seconds EndFunc Func ShowPrimes( $nPrimes ) ConsoleWrite( "$nPrimes = " & _ $nPrimes & @CRLF ) Local $hTimer = TimerInit() Local $aPrimes = CalcPrimes( $nPrimes ) ConsoleWrite( "Time = " & _ TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplay( $aPrimes ) EndFunc Note again that the user code in the pure AutoIt examples above is almost identical to the user code in the AutoIt/VB examples below. The only difference the user will notice is the speed. To calculate 5000 prime numbers, the C#/VB code is 100 times faster. Try yourself. Examples with AutoIt/VB code in VB\ExamplesVB.au3. This is user code: #include <Array.au3> #include "CalcPrimesVB.au3" Opt( "MustDeclareVars", 1 ) ExamplesVB() Func ExamplesVB() CalcPrimesVBInit() ShowPrimesVB( 10 ) ; Used under development ShowPrimesVB( 1000 ) ; 10 milliseconds ShowPrimesVB( 5000 ) ; 80 milliseconds ShowPrimesVB( 10000 ) ; 200 milliseconds ;ShowPrimesVB( 50000 ) ; 5 seconds EndFunc Func ShowPrimesVB( $nPrimes ) ConsoleWrite( "$nPrimes = " & _ $nPrimes & @CRLF ) Local $hTimer = TimerInit() Local $aPrimes = CalcPrimesVB( $nPrimes ) ConsoleWrite( "Time = " & _ TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplay( $aPrimes ) EndFunc .NET assembly dll-file In a production environment the compiled VB code should be stored in a .NET assembly dll-file. The first step is to create the dll-file from the VB source code: #include "..\..\..\..\..\Includes\DotNetAll.au3" ; Compile VB code and load the code into CalcPrimesVB.dll: A .NET assembly dll-file DotNet_LoadVBcode( FileRead( "CalcPrimesVB.vb" ), "System.dll", 0, "CalcPrimesVB.dll" ) ; You can delete the PDB-file (binary file containing debug information) If you inspect the dll-file with ILSpy.exe (see DotNet.au3 UDF) you'll see these comments in top of the output in the right pane window: // ...\7) Create DLL\Prime numbers\VB\CalcPrimesVB.dll // CalcPrimesVB, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // Global type: <Module> // Architecture: AnyCPU (64-bit preferred) // Runtime: .NET 4.0 Note that the dll-file can be used in both 32 and 64 bit code (Architecture: AnyCPU). The second step is to modify the AutoIt/VB UDF to load the code from the dll-file: #include-once #include "..\..\..\..\..\Includes\DotNetAll.au3" Func CalcPrimesVBInit() CalcPrimesVB( 0 ) EndFunc Func CalcPrimesVB( $nPrimes ) Static $oNetCode = 0, $oPrimesClass = 0 If $nPrimes = 0 Or $oNetCode = 0 Then ; Load CalcPrimesVB.dll and create PrimesClass object $oNetCode = DotNet_LoadAssembly( "CalcPrimesVB.dll" ) $oPrimesClass = DotNet_CreateObject( $oNetCode, "PrimesClass" ) If $nPrimes = 0 Then Return EndIf ; Execute CalcPrimes method and return 1D array of primes Return $oPrimesClass.CalcPrimes( $nPrimes ) EndFunc The user code in the examples is exactly the same. But in a production environment the AutoIt user code is usually compiled into an exe-file. Please compile the user code and double click the exe-file to run it. If the AutoIt user code is compiled into an exe-file and the VB dll-file is stored in the same folder as the exe-file, the AutoIt code is always able to find and load the VB dll-file. Summary C# and VB code through .NET Framework is without any doubt the absolute easiest way to execute compiled code in an AutoIt script. It's especially easy because everything (write, compile, load and execute the code and even create an assembly dll-file) can be done through AutoIt. There is no need for any external tools at all. Usually, only 2 lines of AutoIt code are required to make the compiled code available in an AutoIt script. When it comes to calculations and array manipulations, the difference between C#/VB code and AutoIt code is not that big. Under development of C#/VB code (debug) information can be written to SciTE console or a message box. Syntax errors in the code are reported in SciTE console. Because the compiled code is executed as object methods, this solves an otherwise impossible problem of passing arrays back and forth between AutoIt code and compiled code. Posts below Real C# and VB examples. Four examples about generating a 2D array of random data, sorting the array by one or more columns through an index, converting the 2D array to a 1D array in CSV format, and finally saving the 1D array as a CSV file. Post 2. UDF version of examples in post 2. Also a version with a .NET assembly dll-file. Post 3. Adv. C# and VB examples. An introduction to threading. Post 4. Some considerations regarding calculation of prime numbers. Post 7. Optimizing C# and VB code. Optimizing code through multithreading. Optimizing code by storing array as global variable in VB code, thereby avoiding spending time passing arrays back and forth between AutoIt code and VB code. Post 8. Zip-file The zip-file contains two folders: Examples\ and Includes\. Includes\ only contains DotNetAll.au3. You need AutoIt 3.3.10 or later. Tested on Windows 10, Windows 7 and Windows XP. Comments are welcome. Let me know if there are any issues. UsingCSandVB.7z1 point
-
TV-Show-Manager is a small, easy to use application that manages all your favorite tv shows. It is a perfect program for you, if you like watching many tv-shows and need help with keeping track of the airdates and times. Features Manage all your favorite TV-Shows with a single program See all airing times of your shows and how many days/hours/minutes you have to wait for the next episode Don't get confused with all the time zones, TV-Show-Manager converts the airing times to your timezone TV-Schedule - See what shows will be airing in the next 48 hours in US an UK Windows 10 inspired user interface - Customize the user interface with different themes See if your favorit tv shows are canceled or renewed with colored status in your list. Download episodes with one click! (Warning: See notes in full description) Supports link collection for one-click hosters and torrents. (Warning: See notes in full description) Stream episodes with one click (Warning: See notes in full description) I have completely rewritten the program over the past months. It uses the latest version of my MetroGUI UDF and demonstrates what you can do with Autoit if you put in enough time You can download the script and the main program from sourceforge. I have removed all download link collection and other anti-bot-protection bypass features from the script that might be used to damage the site owners. So please don't ask for any of these functions on this forum. Images: Download Script and Main program: https://sourceforge.net/projects/tvshowcountdown/files/1 point
-
The other workaround is to set the file attribute to Read-only, then ShellExecute the file, and then remove the Read-only attribute after the process that opened the file is closed. See example below. Global $sFile = "V:\AutoIt\QuickLaunch\somefile.xlsx" If FileSetAttrib($sFile, "+R") Then Global $iPID = ShellExecute($sFile) EndIf While ProcessExists($iPID) Sleep(10) WEnd FileSetAttrib($sFile, "-R") Adam1 point
-
Sorry about that, unfortunately it won't work since "/r" needs to be before the file name (well it does in my case) otherwise it just opens normally, you could use some type of function for example: #include <WinAPIShPath.au3> _MyShellExecute("V:\AutoIt\QuickLaunch\somefile.xlsx") Func _MyShellExecute($_sFileName) Local $sExtension = _WinAPI_PathFindExtension($_sFileName) Switch $sExtension Case ".xlsx" ShellExecute("Excel.exe", '/r "' & $_sFileName & '"') Case Else ShellExecute($_sFileName) EndSwitch EndFunc1 point
-
Unknown function in AutoIT
Amixg reacted to Au3Builder for a topic
Press F1 in Scite to Open Help File.It contains a lot of useful information.1 point -
Unknown function in AutoIT
Amixg reacted to Au3Builder for a topic
there is no such thing as GuiCtrlGetData. I believe you meant GUICtrlRead.1 point -
1 point
-
(Re)Using a GUI button while in another function
Earthshine reacted to Melba23 for a topic
FlexScott, Welcome to the AutoIt forums. To detect button presses while functions are running, take a look at the Interrupting a running function tutorial in the Wiki. M231 point -
@czardas post #52 might be the single biggest boner for sorting arrays anyone has ever exhibited1 point
-
ControlSend function doesn't work
Earthshine reacted to Gyba for a topic
Wow, thank you for your quick reply. It seems like the solution is WinWait("Untitled - Notepad") function. Thank you so much.1 point -
ControlSend function doesn't work
Earthshine reacted to jdelaney for a topic
If you want to be real anal,you should wait for the window to be present, visible, and enabled. Same with the control, with an added focus. if you do that, your script's success rate will increase dramatically. Especially as it becomes more complex.1 point -
Seeking ways to stop the 'clang'
Earthshine reacted to qwert for a topic
I've made a change to the RegExp to avoid modifying any message message text with the word 'Error'. It now modifies only those with 'Error: '. StringRegExpReplace(StringRegExpReplace($sText, "\([^)]*\)", ""), "(.*)\bError: \b(.*)", "An unsupported file condition has been encounted that prevents this program from continuing. It will now close without completing the requested operation."), _ Thanks to ViciousXUSMC for the link to RegEx101 dot com, where I was able to confirm the improved RegExp.1 point -
junkew, There is no easy to use function (like the CreateObject functions) to handle static methods. The examples that you refer to use concepts and techniques that are so difficult to understand and apply that the examples simply will not be used. It will not happen. The most valuable result of Using .NET libary with AutoIt, possible? is the ability to use C# and VB code. This is the result that can be used without too much trouble of other AutoIt users in addition to the few that were active in the thread. In C# and VB code you can do everything. You can use multi-threaded code, you can use Windows.Forms and you can use static methods. Because C#/VB are popular languages, there are usually always examples that you can copy. And generally all .NET code is much easier to handle in C#/VB than in AutoIt. These languages are .NET languages. Because C# and VB code is accessed as object methods through .NET Framework, data (method parameters) can easily be passed back and forth between AutoIt code and C#/VB code. Even arrays. The objects can be used immediately without any kind of registration. Using C# and VB Code in AutoIt through .NET Framework makes the development process of even complicated code and especially .NET code easy and fast. That's the AutoIt way.1 point
-
I reverted to the earlier version and it seems to be working again. The bug was not apparent because that section of code was being skipped after changes had been made. When I reintroduced insertion sort by changing the range limit back to what it had been previously, the bug showed itself. The logic had been modified and I was unaware of this. I hope there are no more changes I'm unaware of. I hadn't noticed it because I use my own version. Description: Sort a 1D or 2D array on a specific index using the dualpivotsort/quicksort/insertionsort/tagsort algorithms Syntax: _ArraySort ( ByRef $aArray [, $iDescending = 0 [, $iStart = 0 [, $iEnd = 0 [, $iSubItem = 0 [, $iAlternate = 0]]]]] ) $iAlternate [optional] 1D array sorted with PivotSort algorithm 2D array sorted with TagSort algorithm Default: both sorted with QuickSort algorithm Return Value Success: 1. Failure: 0 and sets the @error flag to non-zero. @error: 1 - $aArray is not an array 2 - $iStart is greater than $iEnd 3 - $iSubItem is greater than subitem count 4 - $aArray is not a 1D or 2D array 5 - $aArray is empty 6 - Deprecated Remarks By default the UDF uses a QuickSort algorithm to sort both 1D and 2D arrays. For 1D arrays setting the $iAlternate parameter uses a DualPivotSort algorithm - this can be significantly faster for large arrays (> 50 elements). In each algorithm, relatively short arrays will be sorted using an insertion sort (< 15 elements with QuickSort and TagSort; < 45 elements with Dual PivotSort). For 2D arrays setting the $iAlternate parameter uses a TagSort algorithm - this is considerably faster when dealing with multiple columns. However, this algoritm uses more memory and may not be suitable for large arrays on less powerful machines. Note that there is no guarantee that a specific algorithm will be faster in a given case. CODE: #include <Array.au3> ; #FUNCTION# ==================================================================================================================== ; Author ........: Jos ; Modified.......: LazyCoder - added $iSubItem option; Tylo - implemented stable QuickSort algo; Jos - changed logic to correctly Sort arrays with mixed Values and Strings ; Melba23 - implemented stable pivot algo; czardas - implemented TagSort ; =============================================================================================================================== Func _ArraySort_NEW(ByRef $aArray, $iDescending = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0, $iAlternate = 0) If $iDescending = Default Then $iDescending = 0 If $iStart = Default Then $iStart = 0 If $iEnd = Default Then $iEnd = 0 If $iSubItem = Default Then $iSubItem = 0 If $iAlternate = Default Then $iAlternate = 0 If Not IsArray($aArray) Then Return SetError(1, 0, 0) Local $iUBound = UBound($aArray) - 1 If $iUBound = -1 Then Return SetError(5, 0, 0) ; Bounds checking If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound If $iStart < 0 Then $iStart = 0 If $iStart > $iEnd Then Return SetError(2, 0, 0) ; Sort Switch UBound($aArray, $UBOUND_DIMENSIONS) Case 1 If $iAlternate Then ; Use PivotSort algorithm __ArrayDualPivotSort1D_New($aArray, $iStart, $iEnd) Else __ArrayQuickSort1D_New($aArray, $iStart, $iEnd) EndIf If $iDescending Then _ArrayReverse($aArray, $iStart, $iEnd) Case 2 Local $iSubMax = UBound($aArray, $UBOUND_COLUMNS) - 1 If $iSubItem > $iSubMax Then Return SetError(3, 0, 0) If $iDescending Then $iDescending = -1 Else $iDescending = 1 EndIf If $iAlternate And $iSubMax Then ; Use TagSort algorithm Local $aTrac[$iUBound +1] For $i = $iStart To $iEnd $aTrac[$i] = $i Next __ArrayTagSort2D($aArray, $aTrac, $iDescending, $iStart, $iEnd, $iSubItem, $iSubMax) __ArrayTagSort2D_SwapSeq($aArray, $aTrac, $iStart, $iEnd) Else __ArrayQuickSort2D($aArray, $iDescending, $iStart, $iEnd, $iSubItem, $iSubMax) EndIf Case Else Return SetError(4, 0, 0) EndSwitch Return 1 EndFunc ;==>_ArraySort ; 1D Sort helper functions Func __ArrayQuickSort1D_New(ByRef $aArray, Const ByRef $iStart, Const ByRef $iEnd) If $iEnd <= $iStart Then Return Local $vTmp ; InsertionSort used for small arrays - value chosen empirically If ($iEnd - $iStart) < 15 Then __ArrayInsertSort1D($aArray, $iStart, $iEnd) Return EndIf ; QuickSort Local $L = $iStart, $R = $iEnd, $vPivot = $aArray[Int(($iStart + $iEnd) / 2)], $bNum = IsNumber($vPivot) Do If $bNum Then While ($aArray[$L] < $vPivot And IsNumber($aArray[$L])) Or (Not IsNumber($aArray[$L]) And StringCompare($aArray[$L], $vPivot) < 0) $L += 1 WEnd While ($aArray[$R] > $vPivot And IsNumber($aArray[$R])) Or (Not IsNumber($aArray[$R]) And StringCompare($aArray[$R], $vPivot) > 0) $R -= 1 WEnd Else While (StringCompare($aArray[$L], $vPivot) < 0) $L += 1 WEnd While (StringCompare($aArray[$R], $vPivot) > 0) $R -= 1 WEnd EndIf ; Swap If $L <= $R Then $vTmp = $aArray[$L] $aArray[$L] = $aArray[$R] $aArray[$R] = $vTmp $L += 1 $R -= 1 EndIf Until $L > $R __ArrayQuickSort1D($aArray, $iStart, $R) __ArrayQuickSort1D($aArray, $L, $iEnd) EndFunc ;==>__ArrayQuickSort1D Func __ArrayDualPivotSort1D_New(ByRef $aArray, $iPivot_Left, $iPivot_Right) If $iPivot_Left > $iPivot_Right Then Return Local $iLength = $iPivot_Right - $iPivot_Left + 1 ;Local $i, $j, $k, $iAi, $iAk, $iA1, $iA2, $iLast Local $k ; InsertionSort used for small arrays - value chosen empirically If $iLength < 45 Then __ArrayInsertSort1D($aArray, $iPivot_Left, $iPivot_Right) Return EndIf ; PivotSort Local $iSeventh = BitShift($iLength, 3) + BitShift($iLength, 6) + 1 Local $iE1, $iE2, $iE3, $iE4, $iE5, $t $iE3 = Ceiling(($iPivot_Left + $iPivot_Right) / 2) $iE2 = $iE3 - $iSeventh $iE1 = $iE2 - $iSeventh $iE4 = $iE3 + $iSeventh $iE5 = $iE4 + $iSeventh If $aArray[$iE2] < $aArray[$iE1] Then $t = $aArray[$iE2] $aArray[$iE2] = $aArray[$iE1] $aArray[$iE1] = $t EndIf If $aArray[$iE3] < $aArray[$iE2] Then $t = $aArray[$iE3] $aArray[$iE3] = $aArray[$iE2] $aArray[$iE2] = $t If $t < $aArray[$iE1] Then $aArray[$iE2] = $aArray[$iE1] $aArray[$iE1] = $t EndIf EndIf If $aArray[$iE4] < $aArray[$iE3] Then $t = $aArray[$iE4] $aArray[$iE4] = $aArray[$iE3] $aArray[$iE3] = $t If $t < $aArray[$iE2] Then $aArray[$iE3] = $aArray[$iE2] $aArray[$iE2] = $t If $t < $aArray[$iE1] Then $aArray[$iE2] = $aArray[$iE1] $aArray[$iE1] = $t EndIf EndIf EndIf If $aArray[$iE5] < $aArray[$iE4] Then $t = $aArray[$iE5] $aArray[$iE5] = $aArray[$iE4] $aArray[$iE4] = $t If $t < $aArray[$iE3] Then $aArray[$iE4] = $aArray[$iE3] $aArray[$iE3] = $t If $t < $aArray[$iE2] Then $aArray[$iE3] = $aArray[$iE2] $aArray[$iE2] = $t If $t < $aArray[$iE1] Then $aArray[$iE2] = $aArray[$iE1] $aArray[$iE1] = $t EndIf EndIf EndIf EndIf Local $iLess = $iPivot_Left Local $iGreater = $iPivot_Right If (($aArray[$iE1] <> $aArray[$iE2]) And ($aArray[$iE2] <> $aArray[$iE3]) And ($aArray[$iE3] <> $aArray[$iE4]) And ($aArray[$iE4] <> $aArray[$iE5])) Then Local $iPivot_1 = $aArray[$iE2] Local $iPivot_2 = $aArray[$iE4] $aArray[$iE2] = $aArray[$iPivot_Left] $aArray[$iE4] = $aArray[$iPivot_Right] Do $iLess += 1 Until $aArray[$iLess] >= $iPivot_1 Do $iGreater -= 1 Until $aArray[$iGreater] <= $iPivot_2 $k = $iLess Local $iAk While $k <= $iGreater $iAk = $aArray[$k] If $iAk < $iPivot_1 Then $aArray[$k] = $aArray[$iLess] $aArray[$iLess] = $iAk $iLess += 1 ElseIf $iAk > $iPivot_2 Then While $aArray[$iGreater] > $iPivot_2 $iGreater -= 1 If $iGreater + 1 = $k Then ExitLoop 2 WEnd If $aArray[$iGreater] < $iPivot_1 Then $aArray[$k] = $aArray[$iLess] $aArray[$iLess] = $aArray[$iGreater] $iLess += 1 Else $aArray[$k] = $aArray[$iGreater] EndIf $aArray[$iGreater] = $iAk $iGreater -= 1 EndIf $k += 1 WEnd $aArray[$iPivot_Left] = $aArray[$iLess - 1] $aArray[$iLess - 1] = $iPivot_1 $aArray[$iPivot_Right] = $aArray[$iGreater + 1] $aArray[$iGreater + 1] = $iPivot_2 __ArrayDualPivotSort1D_New($aArray, $iPivot_Left, $iLess - 2) __ArrayDualPivotSort1D_New($aArray, $iGreater + 2, $iPivot_Right) If ($iLess < $iE1) And ($iE5 < $iGreater) Then While $aArray[$iLess] = $iPivot_1 $iLess += 1 WEnd While $aArray[$iGreater] = $iPivot_2 $iGreater -= 1 WEnd $k = $iLess While $k <= $iGreater $iAk = $aArray[$k] If $iAk = $iPivot_1 Then $aArray[$k] = $aArray[$iLess] $aArray[$iLess] = $iAk $iLess += 1 ElseIf $iAk = $iPivot_2 Then While $aArray[$iGreater] = $iPivot_2 $iGreater -= 1 If $iGreater + 1 = $k Then ExitLoop 2 WEnd If $aArray[$iGreater] = $iPivot_1 Then $aArray[$k] = $aArray[$iLess] $aArray[$iLess] = $iPivot_1 $iLess += 1 Else $aArray[$k] = $aArray[$iGreater] EndIf $aArray[$iGreater] = $iAk $iGreater -= 1 EndIf $k += 1 WEnd EndIf __ArrayDualPivotSort1D_New($aArray, $iLess, $iGreater) Else Local $iPivot = $aArray[$iE3] $k = $iLess While $k <= $iGreater If $aArray[$k] = $iPivot Then $k += 1 ContinueLoop EndIf $iAk = $aArray[$k] If $iAk < $iPivot Then $aArray[$k] = $aArray[$iLess] $aArray[$iLess] = $iAk $iLess += 1 Else While $aArray[$iGreater] > $iPivot $iGreater -= 1 WEnd If $aArray[$iGreater] < $iPivot Then $aArray[$k] = $aArray[$iLess] $aArray[$iLess] = $aArray[$iGreater] $iLess += 1 Else $aArray[$k] = $iPivot EndIf $aArray[$iGreater] = $iAk $iGreater -= 1 EndIf $k += 1 WEnd __ArrayDualPivotSort1D_New($aArray, $iPivot_Left, $iLess - 1) __ArrayDualPivotSort1D_New($aArray, $iGreater + 1, $iPivot_Right) EndIf EndFunc ;==>__ArrayDualPivotSort1D Func __ArrayInsertSort1D(ByRef $aArray, Const ByRef $iStart, Const ByRef $iEnd) Local $vCur, $vTmp For $i = $iStart + 1 To $iEnd $vTmp = $aArray[$i] If IsNumber($vTmp) Then For $j = $i - 1 To $iStart Step -1 $vCur = $aArray[$j] If ($vTmp >= $vCur And IsNumber($vCur)) Or (Not IsNumber($vCur) And StringCompare($vTmp, $vCur) >= 0) Then ExitLoop $aArray[$j + 1] = $vCur Next Else For $j = $i - 1 To $iStart Step -1 If (StringCompare($vTmp, $aArray[$j]) >= 0) Then ExitLoop $aArray[$j + 1] = $aArray[$j] Next EndIf $aArray[$j + 1] = $vTmp Next EndFunc ; 2D Sort helper functions ; Existing __ArrayQuickSort2D Func __ArrayTagSort2D(Const ByRef $aArray, ByRef $aTrac, Const ByRef $iStep, Const ByRef $iStart, Const ByRef $iEnd, Const ByRef $iSubItem, Const ByRef $iSubMax) If $iEnd <= $iStart Then Return Local $vTmp ; InsertionSort (faster for smaller segments) If ($iEnd - $iStart) < 15 Then ; Force tagsort For $i = $iStart + 1 To $iEnd $vTmp = $aTrac[$i] ; Follows the same logic as __ArrayQuickSort1D If IsNumber($aArray[$vTmp][$iSubItem]) Then For $j = $i - 1 To $iStart Step -1 If ((($aArray[$vTmp][$iSubItem] * $iStep) >= $aArray[$aTrac[$j]][$iSubItem] * $iStep) And IsNumber($aArray[$aTrac[$j]][$iSubItem])) _ Or (Not IsNumber($aArray[$aTrac[$j]][$iSubItem]) And StringCompare($aArray[$vTmp][$iSubItem], $aArray[$aTrac[$j]][$iSubItem]) * $iStep >= 0) Then ExitLoop $aTrac[$j + 1] = $aTrac[$j] Next Else For $j = $i - 1 To $iStart Step -1 If (StringCompare($aArray[$vTmp][$iSubItem], $aArray[$aTrac[$j]][$iSubItem]) * $iStep >= 0) Then ExitLoop $aTrac[$j + 1] = $aTrac[$j] Next EndIf $aTrac[$j + 1] = $vTmp Next Return EndIf ; TagSort Local $L = $iStart, $R = $iEnd, $vPivot = $aArray[$aTrac[Int(($iStart + $iEnd) / 2)]][$iSubItem], $bNum = IsNumber($vPivot) Do If $bNum Then While ($iStep * ($aArray[$aTrac[$L]][$iSubItem] - $vPivot) < 0 And IsNumber($aArray[$aTrac[$L]][$iSubItem])) Or (Not IsNumber($aArray[$aTrac[$L]][$iSubItem]) And $iStep * StringCompare($aArray[$aTrac[$L]][$iSubItem], $vPivot) < 0) $L += 1 WEnd While ($iStep * ($aArray[$aTrac[$R]][$iSubItem] - $vPivot) > 0 And IsNumber($aArray[$aTrac[$R]][$iSubItem])) Or (Not IsNumber($aArray[$aTrac[$R]][$iSubItem]) And $iStep * StringCompare($aArray[$aTrac[$R]][$iSubItem], $vPivot) > 0) $R -= 1 WEnd Else While ($iStep * StringCompare($aArray[$aTrac[$L]][$iSubItem], $vPivot) < 0) $L += 1 WEnd While ($iStep * StringCompare($aArray[$aTrac[$R]][$iSubItem], $vPivot) > 0) $R -= 1 WEnd EndIf If $L <= $R Then ; Swap $vTmp = $aTrac[$L] $aTrac[$L] = $aTrac[$R] $aTrac[$R] = $vTmp $L += 1 $R -= 1 EndIf Until $L > $R __ArrayTagSort2D($aArray, $aTrac, $iStep, $iStart, $R, $iSubItem, $iSubMax) __ArrayTagSort2D($aArray, $aTrac, $iStep, $L, $iEnd, $iSubItem, $iSubMax) EndFunc ;==>__ArrayTagSort2D Func __ArrayTagSort2D_SwapSeq(ByRef $aArray, ByRef $aTrac, Const ByRef $iStart, Const ByRef $iEnd) Local $iCols = UBound($aArray, 2), $aFirst[$iCols], $i, $iNext For $iInit = $iStart To $iEnd ; initialize each potential overwrite sequence [separate closed system] If $aTrac[$iInit] <> $iInit Then ; rows will now be overwritten in accordance with tracking information $i = $iInit ; set the current row as the start of the sequence For $j = 0 To $iCols -1 $aFirst[$j] = $aArray[$i][$j] ; copy the first row [although we don't know where to put it yet] Next Do For $j = 0 To $iCols -1 $aArray[$i][$j] = $aArray[$aTrac[$i]][$j] ; overwrite each row [following the trail] Next $iNext = $aTrac[$i] ; get the index of the next row in the sequence $aTrac[$i] = $i ; set to ignore rows already processed [may be needed once, or not at all] $i = $iNext ; follow the trail as far as it goes [indices could be higher or lower] Until $aTrac[$i] = $iInit ; all tracking sequences end at this juncture For $j = 0 To $iCols -1 $aArray[$i][$j] = $aFirst[$j] ; now we know where to put the initial row we copied earlier Next $aTrac[$i] = $i ; set to ignore rows already processed [as above] EndIf Next EndFunc ;==> __ArrayTagSort2D_SwapSeq1 point
-
Hey, Thanks alot it finally works, ive been looking for this for so long. Thank you!1 point
-
And you can get more information on your element like this _UIA_HighLight($omega) _UIA_getBasePropertyInfo($omega) _UIA_getAllPropertyValues($omega)1 point
-
kosamja, AutoIt now has 2 functions for displaying arrays: _ArrayDisplay: A quick way to see the contents of an array, with little user interaction, _DebugArrayDisplay: A more complex GUI which allows you more actions (including stopping the script) - essentially the old _ArrayDisplay. The former is designed for scripts where a user might wish to see the contents of an array, but you do not want them to have access to too many options. M231 point
-
I call that "bot program" AutoIt3. Jos1 point
-
Using C# and VB Code in AutoIt through .NET Framework
IndianSage reacted to LarsJ for a topic
Real C# and VB examples One of the great advantages of AutoIt is that the code development process is easy and fast. One of the (few) disadvantages is that the code execution speed is limited by the fact that AutoIt is an interpreted language. Especially calculations in loops eg. calculations on arrays with many elements can be slow compared to the speed of the same calculations in compiled code. Another problem related to arrays is that AutoIt arrays cannot easily be accessed from compiled languages. Nearly a year ago, a technique was introduced in Accessing AutoIt Variables to access AutoIt arrays from compiled code. But this technique is complicated and external development tools are needed to generate the compiled code. The possibility to use C# and VB code in AutoIt through .NET Framework makes it easy to execute compiled code in an AutoIt script, and it makes it easy to pass arrays back and forth between the AutoIt code and the compiled code. And everything (write, compile, load and execute the code and even create an assembly dll-file) can be done through AutoIt. Although it's different languages, the difference between pure calculations and loops is often not so great. If the C# and VB code is restricted to a single function or a single central loop, that's crucial for the execution speed, it should not be too hard to convert AutoIt code to C# or VB code. With the possibility to use C# and VB code in AutoIt through .NET Framework, processing loops and arrays in compiled code has never been easier. C# and VB are very popular programming languages. There are literally millions of examples on the internet. This means that you almost never have to start completely from scratch. You can almost always find an example to copy. Four new examples In first post, an example of calculating prime numbers has been examined. The C#/VB code is 100 times faster than the AutoIt code. This post is a review of four new examples. The examples are about generating a 2D array of random data, sorting the array by one or more columns through an index, converting the 2D array to a 1D array in CSV format, and finally saving the 1D array as a CSV file. The purpose of the examples is to show how to convert AutoIt code to compiled code in different but common areas. The examples also shows which types of code can be optimized and which types of code cannot be much optimized. The compiled code in these examples is VB code. There is no C# code. For each example there is an implementation in pure AutoIt code, and an implementation in AutoIt/VB code. Files related to optimized AutoIt/VB code has "Opt" in the file name. A little bit of error checking is done in each of the examples. At least checking function parameters. All error checking is of course done in AutoIt code. There seems not to be much point in optimizing error checking with compiled code. The examples are added to the zip-file in bottom of first post. They are stored in Examples\2) Real C# and VB examples\. All four examples are structured in the same way. There is a main folder and two subfolders: Examples\ and Includes\. The subfolders contains a handful of files. The code in the second example is a continuation of the code in the first example. The code in the third example is a continuation of the code in the first and second example. The code in the last example is a continuation of the code in the previous examples. If you want to try all the examples at once you can go directly to the last example. If you run the example with pure AutoIt code and the example with optimized AutoIt/VB code, you can easily get an impression of the speed difference. Because arrays and CSV-files are large arrays and files, they are shown in virtual listviews with _ArrayDisplayEx() and CSVfileDisplay(). These functions are stored in Display\ folder in the zip-file. Below is a review of the four examples with focus on the second example about sorting. Generate random data The code in this example creates a 2D array of random data where the columns can contain 5 different data types: strings, integers, floats (doubles), dates and times. Dates and times are integers on the formats yyyymmdd and hhmmss, and are created as correct dates and times. See Includes\Rand2DArray.txt for documentation. The optimized AutoIt/VB code is about 10 times faster than the pure AutoIt code. Index based sorting A 2D array can be sorted by one or more columns. Sorting by more columns is relevant if the columns contains duplicates. A column can be sorted as either strings or numbers (integers or floats) in ascending or descending order. See Includes\Sort2DArray.txt for documentation. That it's an index based sorting means that the array itself is not sorted but that an index is created that contains the array row indices in an order that matches the sorting order. This is usually a good sorting technique for arrays with many rows and columns where more than one column is included in the sorting. And it makes it possible to sort the same array in several ways by creating multiple sorting indexes. This is the AutoIt sorting code: ; Index based sorting of a 2D array by one or more columns. Returns the ; sorting index as a DllStruct (Sort2DArray) or an array (Sort2DArrayOpt). Func Sort2DArray( _ $aArray, _ ; The 2D array to be sorted by index $aCompare ) ; Info about columns used in sorting, see 1) in docu ; Check parameters ; ... Local $iRows = UBound( $aArray ) Local $iCmps = UBound( $aCompare ) Local $tIndex = DllStructCreate( "uint[" & $iRows & "]" ) Local $pIndex = DllStructGetPtr( $tIndex ) Static $hDll = DllOpen( "kernel32.dll" ) ; Sorting by multiple columns Local $lo, $hi, $mi, $r, $j For $i = 1 To $iRows - 1 $lo = 0 $hi = $i - 1 Do $r = 0 ; Compare result (-1,0,1) $j = 0 ; Index in $aCompare array $mi = Int( ( $lo + $hi ) / 2 ) While $r = 0 And $j < $iCmps $r = ( $aCompare[$j][1] ? StringCompare( $aArray[$i][$aCompare[$j][0]], $aArray[DllStructGetData($tIndex,1,$mi+1)][$aCompare[$j][0]] ) : _ $aArray[$i][$aCompare[$j][0]] < $aArray[DllStructGetData($tIndex,1,$mi+1)][$aCompare[$j][0]] ? -1 : _ $aArray[$i][$aCompare[$j][0]] > $aArray[DllStructGetData($tIndex,1,$mi+1)][$aCompare[$j][0]] ? 1 : 0 ) * $aCompare[$j][2] $j += 1 WEnd Switch $r Case -1 $hi = $mi - 1 Case 1 $lo = $mi + 1 Case 0 ExitLoop EndSwitch Until $lo > $hi DllCall( $hDll, "none", "RtlMoveMemory", "struct*", $pIndex+($mi+1)*4, "struct*", $pIndex+$mi*4, "ulong_ptr", ($i-$mi)*4 ) DllStructSetData( $tIndex, 1, $i, $mi+1+($lo=$mi+1) ) Next Return $tIndex EndFunc Note that a DllStruct is used to implement the sorting index. And this is the VB sorting code: Public Function Sort2DArray( aObjects As Object(,), aCompare As Object(,) ) As Integer() Dim iRows As Integer = aObjects.GetUpperBound(1) + 1 Dim iCmps As Integer = aCompare.GetUpperBound(1) + 1 Dim MyList As New Generic.List( Of Integer ) MyList.Capacity = iRows MyList.Add(0) 'Sorting by multiple columns Dim lo, hi, mi, r, j As Integer For i As Integer = 1 To iRows - 1 lo = 0 hi = i - 1 Do r = 0 'Compare result (-1,0,1) j = 0 'Index in $aCompare array mi = ( lo + hi ) / 2 While r = 0 And j < iCmps r = If( aCompare(1,j), String.Compare( aObjects(aCompare(0,j),i), aObjects(aCompare(0,j),MyList.Item(mi)) ), If( aObjects(aCompare(0,j),i) < aObjects(aCompare(0,j),MyList.Item(mi)), -1, If( aObjects(aCompare(0,j),i) > aObjects(aCompare(0,j),MyList.Item(mi)), 1, 0 ) ) ) * aCompare(2,j) j += 1 End While Select r Case -1 hi = mi - 1 Case 1 lo = mi + 1 Case 0 Exit Do End Select Loop Until lo > hi MyList.Insert( If(lo=mi+1,mi+1,mi), i ) Next Return MyList.ToArray() End Function Here MyList is used to implement the sorting index. A list in VB is a 1D array where items can be inserted into the list without the need for manually (in a loop) to move subsequent items a row down to get room for the new item. This is handled internally in the implementation of the list. In both the AutoIt and VB code, the index is created through a binary sorting and insertion algorithm. Note the similarity between the AutoIt and the VB code. Due to the list the VB code seems to be the easiest code. The optimized AutoIt/VB code is about 10 times faster than the pure AutoIt code. Convert array The 2D array is converted into a 1D array of strings in CSV format. The most remarkable of this example is that the AutoIt/VB code is only 1-2 times faster than the pure AutoIt code. There are mainly two reasons for this. Firstly, it's very simple code and that's to the advantage of the AutoIt code. Secondly, the COM conversions (discussed in a section in Accessing AutoIt Variables) plays an important role. And that's to the disadvantage of the VB code. Save array In the last example the 1D array of strings is saved as a CSV file. The AutoIt/VB code is a bit faster than the pure AutoIt code. The execution speed is predominantly determined by how fast a file can be written to the disk drive. This takes approximately equal time in VB and AutoIt code. Note that the VB code does not contain a loop to save the strings. There is an internal function for storing a 1D array of strings. Zip-file at bottom of first post is updated.1 point -
I was needing to get SHA-256 from some file. and I made this. #include <File.au3> Opt("MustDeclareVars",1) Global Const $iHashLen=32 Global Const $Advapi32="Advapi32.dll" Global Const $PROV_RSA_AES=24 Global Const $CALG_SHA_256=0x0000800c Global Const $CRYPT_VERIFYCONTEXT = 0xF0000000 Global Const $HP_HASHVAL=0x0002 Local $aFiles=_FileListToArray(@SystemDir,"*.exe",1,True) _ArrayDisplay($aFiles) Local $aFiles2[UBound($aFiles)-1][2] For $i= 1 to $aFiles[0] $aFiles2[$i-1][0]=$aFiles[$i] $aFiles2[$i-1][1]=SHA256($aFiles[$i]) Next _ArrayDisplay($aFiles2) Func SHA256($sFile) Local $hCryptProv=0 Local $hHash=0 Local $Ret = 0 Local $iSize=0 Local $tBuffer=0 Local $hHash=0 Local $tHashData=0 Local $sHASH="" if not FileExists($sFile) Then Return "" $iSize=FileGetSize($sFile) $Ret = DllCall($Advapi32, "bool", "CryptAcquireContextW", "handle*", 0, "ptr", NULL, "ptr", Null,"dword",$PROV_RSA_AES,"dword",$CRYPT_VERIFYCONTEXT) ConsoleWrite("+ CryptAcquireContextW Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF) $hCryptProv=$Ret[1] ConsoleWrite("$hCryptProv= " & $hCryptProv & @CRLF) $Ret = DllCall($Advapi32, "bool", "CryptCreateHash", "handle", $hCryptProv, "dword",$CALG_SHA_256,"dword",0,"dword",0,"handle*",0) ConsoleWrite("+ CryptCreateHash Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF) $hHash=$Ret[5] ConsoleWrite("$pHash= " & $hHash & @CRLF) $tBuffer=DllStructCreate("byte Data[" & $iSize & "]") $tBuffer.Data=FileRead($sFile) $Ret = DllCall($Advapi32, "bool", "CryptHashData", "handle", $hHash,"ptr",DllStructGetPtr($tBuffer),"dword",DllStructGetSize($tBuffer),"dword",0) ConsoleWrite("+ CryptHashData Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF) $tHashData=DllStructCreate("byte[" & $iHashLen & "]") $Ret = DllCall($Advapi32, "bool", "CryptGetHashParam", "handle", $hHash, "dword",$HP_HASHVAL,"ptr",DllStructGetPtr($tHashData),"dword*",$iHashLen,"dword",0) ConsoleWrite("+ CryptGetHashParam Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF) For $i=1 to $iHashLen $sHASH&=Hex(DllStructGetData($tHashData, 1, $i), 2) Next if $hHash Then $Ret = DllCall($Advapi32, "bool", "CryptDestroyHash", "handle",$hHash) ConsoleWrite("+ CryptDestroyHash Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF) EndIf If $hCryptProv Then $Ret = DllCall($Advapi32, "bool", "CryptReleaseContext", "handle", $hCryptProv, "dword",0) ConsoleWrite("+ CryptReleaseContext Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF) EndIf $tBuffer=Null $tHashData=Null Return $sHASH EndFunc Saludos1 point