Leaderboard
Popular Content
Showing content with the highest reputation on 05/30/2021 in all areas
-
WHAT : is .NET Common Language Runtime (CLR) Framework The Common Language Runtime (CLR) is a an Execution Environment . Common Language Runtime (CLR)'s main tasks are to convert the .NET Managed Code to native code, manage running code like a Virtual Machine, and also controls the interaction with the Operating System. As part of Microsoft's .NET Framework, the Common Language Runtime (CLR) is managing the execution of programs written in any of several supported languages. Allowing them to share common object-oriented classes written in any of the languages. HOW : To access the CLR environment you need to create an Appdomain Object - _CLR_GetDefaultDomain() An AppDomain provides an isolated region in which code runs inside of an existing process. Application domains provide an isolation boundary for security, reliability, and versioning, and for unloading assemblies. Application domains are typically created by runtime hosts, which are responsible for bootstrapping the common language runtime before an application is run. WHEN : Would you use CLR Runtime Hosts 1. To access .NET Class Libraries : System System.Collections System.Data System.Drawing System.IO System.Text System.Threading System.Timers System.Web System.Web.Services System.Windows.Forms System.Xml 2. Accessing custom build .Net Assemblies : Some Examples (but there are a ton out there) AutoItX3 - The .NET Assembly for using AutoItX JSonToXML libr. XMLRPC Libr. .NETPDF libr. .NETOCR Libr WInSCP Libr. ... 3. To Compile .Net Code into an Assembly 4. To Run C# or VB.net Code 5. To Mix AU3 and .Net functionality in your Application WHERE : To find documentation about CLR First of all you can find a lot on MSDN and here : Post 4 & Post 6 EXAMPLES : Multiple examples included in Zip !! Example : “System.Text.UTF8Encoding” Example : “System.IO.FileInfo” Example : “System.Windows.Forms” Example : AutoItX3 Custom .NET Assembly AutoItX Example : Compile Code C# and Code VB Example : Compile Code C# at Runtime WHO : Created the CLR.au3 UDF All credits go to : Danyfirex / Larsj / Trancexx / Junkew TO DO : The library is still Work in Process … (Some of the GUI Controls are not yet working as expected...) Anyone is free to participate in contributing to get the bugs resolved and to expand the CLR.au3 functionality ... Enjoy !! DOWNLOADS : (Last updated) - added CLR Constants.au3 - Danyfirex - Global Constants added (Magic numbers) - added .NET CLR CreateObject vs ObjCreate Example.au3 - Junkew • 2 approaches give the same result (only valid for COM Visible Assembly) • Includes a function that shows you which Assembly Classes are COM Visible - added .Net Conventional COM Objects Examples - ptrex - added .NET CLR CreateComInstanceFrom Example - Danyfirex - You can use it for Regfree COM Assembly Access - System.Activator has 4 methods : • CreateComInstanceFrom : Used to create instances of COM objects. • CreateInstanceFrom : Used to create a reference to an object from a particular assembly and type name. • GetObject : Used when marshaling objects. • CreateInstance : Used to create local or remote instances of an object. - added .NET Access SafeArrays Using AccVarsUtilities Example - LarsJ - added SafeArray Utilities functions in Includes - LarsJ - added .NET Access Native MSCorLib Classes - System - ptrex Multiple System Class Examples : • System.Random • System.DateTime • System.Diagnostics.PerformanceCounter • System.IO.FileInfo • System.Int32 • System.Double • System.Speech • System.Web - added Third Party Assembly Access - ptrex • WinSCP : https://winscp.net/eng/download.php • IonicZip : http://dotnetzip.codeplex.com/ - added more Examples using PowerShell GUI Assembly Access - ptrex • GUI Ribbon .NET Assembly using CLR Library • GUI Report Designer .NET Assembly using CLR Library • GUI SSRS Reporting .NET Assembly using CLR Library CLRv3a.zip .NET CLR Framework for AutoIT.pdf1 point
-
Working with DllCall and DllStruct on a ZeroMQ UDF (Questions)
JockoDundee reacted to Nine for a topic
Mirage ? Excessive use of prohibited substance ? Magical mystery ?1 point -
RAGrid grid custom control
Earthshine reacted to LarsJ for a topic
You can also add Using C# and VB Code in AutoIt through .NET Framework to the list of references above. However, an approach based on one of the options already mentioned is probably both cumbersome and time consuming. An easier solution is to try to simulate a grid control with a listview: Replace the entire row selection with a single cell selection, make it possible to move the selected cell around the listview with the arrow keys and finally make it possible to edit the selected cell. The listview should be a virtual listview with an array as the data source, so that when you edit a listview cell you store the new value directly in the data source.1 point -
As your link points out, the declaration of the function is: void zmq_version (int *major, int *minor, int *patch); The test script below works for me: #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #include <Constants.au3> zeromq_test() Func zeromq_test() Local $aResult $aResult = DllCall("libzmq-v142-mt-4_3_4.dll", "none", "zmq_version", _ "int*", Null, _ ;Major "int*", Null, _ ;Minor "int*", Null) ;Patch If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "DllCall Error - @error = " & @error) ConsoleWrite(StringFormat("zeroMQ Version = %s.%s.%s", $aResult[1], $aResult[2], $aResult[3]) & @CRLF) EndFunc Console Output: zeroMQ Version = 4.3.41 point
-
TheXman, Suspicion on vertically merged rows confirmed. I modified your program very slightly to show when we hit a COM error and attached Word file show it hitting the COM error. ;from https://www.autoitscript.com/forum/topic/205953-trying-to-get-columns-in-a-row-for-a-word-table-solved/ ;#AutoIt3Wrapper_run_debug_mode=Y ;use this to debug in console window <--- LOOK #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w- 5 -w 6 -d #include <Constants.au3> #include <Word.au3> example() Func example() Local $oComErr, $oWord, $oRange ;Define local COM error handler $oComErr = ObjEvent("AutoIt.Error", "com_error_handler") If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to create COM error handler - @error = " & @error) ;Create a Word app object $oWord = _Word_Create() If @error Then Exit ConsoleWrite("Unable to create Word object. @error = " & @error & @CRLF) ;Open doc _Word_DocOpen($oWord, "word-merged-cell-table-docv3Z.docx", Default, Default, True) If @error Then Exit ConsoleWrite("Unable to open Word doc. @error = " & @error & @CRLF) ;Display table information With $oWord.ActiveDocument.Tables(1) ConsoleWrite("Table columns = " & .Columns.Count & @CRLF) ConsoleWrite("Table rows = " & .Rows.Count & @CRLF) ;Display number of cells in each row ConsoleWrite(@CRLF) For $i = 1 To .Rows.Count ConsoleWrite(StringFormat("Row %i cell count = %i", $i, .Rows($i).Cells.Count) & @CRLF) Next ;Display row values ConsoleWrite(@CRLF & "Table values with (col width)" & @CRLF) For $iRow = 1 To .Rows.Count For $iCol= 1 To .Rows($iRow).Cells.Count ;Get cell range and strip "end of cell" marker $oRange = .Cell($iRow, $iCol).Range $oRange.End = $oRange.End - 1 ;Ouput cell value with col widths so you know if it is a merged column ConsoleWrite(StringFormat("%s (%s)", $oRange.Text, Round(.Cell($iRow, $iCol).Width))) If $iCol < .Rows($iRow).Cells.Count Then ConsoleWrite(@TAB & @TAB) Next ConsoleWrite(@CRLF) Next EndWith ;Close doc and app _Word_Quit($oWord) EndFunc Func com_error_handler($oError) ConsoleWrite("-Hit a COM error"&@CRLF) ;show in Orange Return ;Return so @error can be trapped by the calling function EndFunc So it appears that there is no clean way but to use COM Exceptions to figure out the columns in a Word Table with merged cells 😒 word-merged-cell-table-docv3Z.docx1 point
-
mike1950r & JockoDundee, Here is a version with the possibility to embed a standard icon within the button parameter: ExtMsgBox_Flag.au3 And an example script: #include <MsgBoxConstants.au3> #include "ExtMsgBox_Flag.au3" $sTitle = "Example 1 title" $sMessage = "Example 1 message" ; Embedded ? icon overrides the standalone INFO icon _ExtMsgBox($MB_ICONINFORMATION, BitOR($MB_ICONQUESTION, $MB_OKCANCEL, $MB_DEFBUTTON2), $sTitle, $sMessage) $sTitle = "Example 2 title" $sMessage = "Example 2 message" ; Embedded ? icon overrides the standalone warning icon _ExtMsgBox($MB_ICONWARNING, BitOR($MB_YESNOCANCEL, $MB_DEFBUTTON3, $MB_ICONQUESTION), $sTitle, $sMessage) $sTitle = "Example 3 title" $sMessage = "Example 3 message" ; Only embedded _ExtMsgBox(0, BitOR($MB_OK, $MB_DEFBUTTON1, $MB_ICONINFORMATION), $sTitle, $sMessage) $sTitle = "Example 4 title" $sMessage = "Example 4 message" ; Only standalone _ExtMsgBox($MB_ICONWARNING, BitOR($MB_OK, $MB_DEFBUTTON1), $sTitle, $sMessage) $sTitle = "Example 5 title" $sMessage = "Example 5 message" ; UAC _ExtMsgBox(8, BitOR($MB_OK, $MB_DEFBUTTON1), $sTitle, $sMessage) $sTitle = "Example 6 title" $sMessage = "Example 6 message" ; Countdown _ExtMsgBox(128, BitOR($MB_OK, $MB_DEFBUTTON1), $sTitle, $sMessage, 10) At present an icon constant embedded in the button parameter overrides the main icon parameter. Should it be that way around or should it be the reverse? M231 point
-
EasyCodeIt - cross-platform AutoIt implementation
seadoggie01 reacted to TheSaint for a topic
Inherent restrictions of Linux aside.1 point -
EasyCodeIt - cross-platform AutoIt implementation
seadoggie01 reacted to TheDcoder for a topic
No way! I promise to finish it before your time runs out... so that you can finally enjoy the fruits of Linux without any restrictions Disclaimer: The above mentioned text should not be, in any way, be constructed into a contract, promise, guarantee or any other type of bond with liability1 point -
Don't worry bud, I have faith in you, and have already come to terms with the imminent release of EasyCodeIt, just after my demise, some time in the future (far hopefully), in the full knowledge you will dedicate it to my memory.1 point
-
1 point
-
TheXman - Once I'm stuck again I'll seek help - it's not fair to bother anyone until I have nailed down my issue. JackoDundee - thanks. However knowing the table has a split/merged cells still does not solve the issue of traversing the table. I'm working on it now and as noted it appears throwing an exception is one way to be alerted that the accessed cell is a split/merged cell. This keyboard cowboy is back to the QWERTY mines 🤪1 point
-
Using SetError with a COM handler [Solved]
JockoDundee reacted to TheXman for a topic
The example below shows how the error object can be used within the function. Notice that all the COM error handler function does is return control back to the caller so that it can process the error. #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w- 5 -w 6 -d #include <Constants.au3> example() Func example() Local $oComErr, $oApp ;Define local COM error handler $oComErr = ObjEvent("AutoIt.Error", "com_error_handler") If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to create COM error handler - @error = " & @error) ;Generate a COM error to show how it can be handled within the function $oApp = ObjCreate("SomeApp.Application") If @error Then With $oComErr ConsoleWrite(@CRLF & "COM ERROR DETECTED!" & @CRLF) ConsoleWrite(" Error ScriptLine....... " & .scriptline & @CRLF) ConsoleWrite(" Error Number........... " & "0x" & Hex(.number) & " (" & .number & ")" & @CRLF) ConsoleWrite(" Error WinDescription... " & StringStripWS(.windescription, $STR_STRIPTRAILING) & @CRLF) ConsoleWrite(" Error Description...... " & StringStripWS(.description , $STR_STRIPTRAILING) & @CRLF) ConsoleWrite(" Error RetCode.......... " & "0x" & Hex(Number(.retcode)) & " (" & Number(.retcode) & ")" & @CRLF) EndWith Exit EndIf EndFunc Func com_error_handler($oError) Return ; Return so @error can be trapped by the calling function EndFunc Console COM ERROR DETECTED! Error ScriptLine....... 16 Error Number........... 0x800401F3 (-2147221005) Error WinDescription... Invalid class string Error Description...... Error RetCode.......... 0x00000000 (0)1 point -
Easy Mp3 v.1.1
KaFu reacted to abberration for a topic
Hello, all! Today I present to you an updated version of Easy Mp3. After releasing version 1.0, I found several bugs that I fixed and added a few new features. Details can be found in the Changelog (check the Help menu). What makes Easy Mp3 special? Ease of use. I started this project because I love FLAC, but my car stereo does not and the transcoding programs out there are tedious to work with, have confusing settings, you cannot drop multiple folders into it and get a good result and finally, the nagging to buy it or check for updates. When you drag & drop a folder full of music, this program adds every supported file into the list of things to encode. All you have to do is select an output folder (personally, I have one folder called Mp3s). By default, it will create the same folder structure of the one that you dropped into it and it will place all of the encoded files in the respective folders. You also have the option to create folders from the metadata contained in the media. Here's what will convince you that this is the best Mp3 transcoder: download an entire discography by your favorite band and drop it into the program, select your output folder and click Encode. It's so simple, you will be amazed. By default, it uses the highest quality settings possible. It makes use of FFMpeg's built-in LAME codec. The download links are at the bottom of the screen. This package includes 32 & 64 bit executables, a user guide, a changelog and source code. I use this program all the time and I hope you love it as much as I had fun scripting it! Enjoy! Download from MEGA: Full package (includes FFMpeg): https://mega.nz/file/SXwUBK7L#aAN_6rDKi1tauQ0ngA4L0pUtD7S7rg66a9IUsl1say0 Lite Package (no FFMpeg): https://mega.nz/file/WLhynA5I#jEg-hnXCTEiWwM21vID9jUgZjaIKihl4pwEe4eQ2FV8 Download from FileFactory: Full package: http://www.filefactory.com/file/5gen99g7hsr6/Easy_Mp3_v1.1_Full.zip Lite package: http://www.filefactory.com/file/74xq8b69gso/Easy_Mp3_v1.1_Lite.zip1 point -
Incremental search in owner and custom drawn ListViews
pixelsearch reacted to Norm73 for a topic
1 point -
mike1950r, This is more elegant, but does rely on "magic numbers": #include <MsgBoxConstants.au3> #include "ExtMsgBox.au3" $sTitle = "Example 1 title" $sMessage = "Example 1 message" $hFlag = BitOR($MB_OKCANCEL, $MB_DEFBUTTON2, $MB_ICONQUESTION) _DialogMessageBox($sTitle, $sMessage, $hFlag) $sTitle = "Example 2 title" $sMessage = "Example 2 message" $hFlag = BitOR($MB_YESNOCANCEL, $MB_DEFBUTTON3, $MB_ICONQUESTION) _DialogMessageBox($sTitle, $sMessage, $hFlag) $sTitle = "Example 3 title" $sMessage = "Example 3 message" $hFlag = BitOR($MB_OK, $MB_DEFBUTTON1, $MB_ICONINFORMATION) _DialogMessageBox($sTitle, $sMessage, $hFlag) $sTitle = "Example 4 title" $sMessage = "Example 4 message" $hFlag = BitOR($MB_OK, $MB_DEFBUTTON1, $MB_ICONWARNING) _DialogMessageBox($sTitle, $sMessage, $hFlag) Func _DialogMessageBox($sTitle, $sMessage, $hFlag) ; Remove all high level flags $hFlag = Mod($hFlag, 4096) ; Determine default button $iDefButton = Floor($hFlag / 256) $hFlag -= 256 * $iDefButton ; Determine icon $iIcon = 16 * Floor($hFlag / 16) $hFlag -= $iIcon ; Determine button text Switch $hFlag Case 0 $sButtonText = "OK" Case 1 $sButtonText = "OK|Cancel" Case 2 $sButtonText = "Abort|Retry|Cancel" Case 3 $sButtonText = "Yes|No|Cancel" Case 4 $sButtonText = "Yes|No" Case 5 $sButtonText = "Retry|Cancel" Case 6 $sButtonText = "Cancel|Try Again|Cancel" EndSwitch ; Add default button flag $iIndex = StringInStr($sButtonText, "|", 2, $iDefButton) If $iIndex Then $sButtonText = StringLeft($sButtonText, $iIndex) & "~" & StringMid($sButtonText, $iIndex + 1) EndIf $iRet = _ExtMsgBox($iIcon, $sButtonText, $sTitle, $sMessage) EndFunc Up to you which you prefer. M231 point
-
Incremental search in owner and custom drawn ListViews
Gianni reacted to pixelsearch for a topic
Hi, version "2q" below includes LarsJ column align. It is based on WM_DRAWITEM and it will be my last update for the moment. #include <ComboConstants.au3> #include <EditConstants.au3> #include <GuiListView.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include "RandomArray.au3" ; LarsJ #include "DrawItem.au3" ; " Opt("MustDeclareVars", 1) Global $g_iRows = 1000, $g_iCols = 6, $g_hGui, $g_hListView, $g_hHeader, $g_hEdit Global $g_aCols = ["Strings", "Integers", "Floats", "Dates", "Times", "R/C"], $g_aWidths = [230, 61, 124, 70, 60, 60] Global $g_aColAligns[$g_iCols] = [$HDF_CENTER, $HDF_RIGHT, $HDF_RIGHT, $HDF_RIGHT, $HDF_RIGHT, $HDF_RIGHT] ; $HDF_LEFT, $HDF_RIGHT, $HDF_CENTER Global $g_idListView, $g_idMarker, $g_idComboCol, $g_idComboColDummy, $g_idEditDummy Global $g_sSearch, $g_iSearchCol, $g_iSortDir, $g_iSearch = $g_iRows Global $g_aArray, $g_aSubArray, $g_tDefaultIndex, $g_tIndex = DllStructCreate("uint arr[" & $g_iRows & "]") Global $g_aIndex[$g_iCols], $g_aIndexTemp[$g_iCols] ; VarGetType's : $g_aIndex => "Array", $g_aIndex[0] => "String" Global $fListViewHasFocus = 1 ; trying this for now, we'll see... Example() Func Example() ; Generate array & one index _Generate_All($g_aArray) $g_aSubArray = $g_aArray $g_tDefaultIndex = $g_tIndex ; Create GUI $g_hGui = GUICreate("Virtual ListView + match 1 or All columns + Align (2q)", 630 + 20, 788 + 30 + 20) ; Create Edit control (search) + dummy control Local $idEdit = GUICtrlCreateEdit("", 120, 10, 305, 20, BitXOR($GUI_SS_DEFAULT_EDIT, $WS_HSCROLL, $WS_VSCROLL)) $g_hEdit = GUICtrlGetHandle($idEdit) $g_idEditDummy = GUICtrlCreateDummy() ; Create ComboBox control (how to search : RegEx or Normal ?) Local $idSearchHow = GUICtrlCreateCombo("RegEx search", 11, 9, 100, 20, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST)) Local $sSearchHow = "RegEx search", $sSearchHowPrev = $sSearchHow ; default way of searching (changeable) GUICtrlSetData($idSearchHow, "Normal search", $sSearchHow) ; Create ComboBox control (column where to search, possible All) + dummy control GUICtrlCreateLabel("Col", 429, 10, 20, 20, BitOR($SS_CENTERIMAGE, $SS_CENTER)) $g_idComboCol = GUICtrlCreateCombo("All", 452, 9, 41, 20, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST)) Local $sSearchCol = "All" ; default column where to search (changeable) => becomes $g_iSearchCol $g_iSearchCol = ($sSearchCol == "All" ? - 1 : Number($sSearchCol)) ; - 1 means search All columns Local $iSearchColPrev = $g_iSearchCol For $i = 0 To $g_iCols - 1 GUICtrlSetData($g_idComboCol, $i & "|", $g_iSearchCol) Next $g_idComboColDummy = GUICtrlCreateDummy() ; Create Label control (number of matching results) Local $idResult = GUICtrlCreateLabel(" " & $g_iRows & " rows (no pattern)", 501, 10, 135, 20, BitOR($SS_CENTERIMAGE, $SS_SUNKEN)) ; Create ListView $g_idListView = GUICtrlCreateListView("", 10, 40, 630, 788, BitOr($LVS_OWNERDATA, $LVS_OWNERDRAWFIXED), $WS_EX_CLIENTEDGE) _GUICtrlListView_SetExtendedListViewStyle($g_idListView, BitOr($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT)) $g_hListView = GUICtrlGetHandle($g_idListView) $g_hHeader = _GUICtrlListView_GetHeader($g_idListView) For $i = 0 To $g_iCols - 1 _GUICtrlListView_AddColumn($g_idListView, $g_aCols[$i], $g_aWidths[$i]) _GUICtrlHeader_SetItemFormat($g_hHeader, $i, $HDF_STRING + $g_aColAligns[$i]) Next ; No ListView column resizing by dragging header dividers (LarsJ) ;_WinAPI_SetWindowLong( $hHeader, $GWL_STYLE, _WinAPI_GetWindowLong( $hHeader, $GWL_STYLE ) + $HDS_NOSIZING ) ; AutoIt 3.3.14.5 issue DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "SetWindowLongPtrW" : "SetWindowLongW", "hwnd", $g_hHeader, "int", $GWL_STYLE, "long_ptr", _ DllCall( "user32.dll", "long_ptr", @AutoItX64 ? "GetWindowLongPtrW" : "GetWindowLongW", "hwnd", $g_hHeader, "int", $GWL_STYLE )[0] + $HDS_NOSIZING ) ; Create Marker (an orange line placed above the header of the column being searched) $g_idMarker = GUICtrlCreateLabel("", 0, 0) GUICtrlSetBkColor(-1, 0xFFA060) ; orange _MoveMarker($g_iSearchCol) _GUICtrlListView_SetSelectedColumn($g_idListView, $g_iSearchCol) ; Sorting information $g_iSortDir = $HDF_SORTUP Local $iSortCol = -1, $iSortColPrev = -1 ; Register message handlers GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM") GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; for LV header only GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") ; Sets the virtual number of items in a virtual list-view control GUICtrlSendMsg($g_idListView, $LVM_SETITEMCOUNT, $g_iRows, 0) GUISetState(@SW_SHOW) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $g_idComboCol, $g_idComboColDummy, $idSearchHow $sSearchCol = GUICtrlRead($g_idComboCol) $g_iSearchCol = ($sSearchCol == "All" ? - 1 : Number($sSearchCol)) ; - 1 means search All columns $sSearchHow = GUICtrlRead($idSearchHow) Select Case $g_iSearchCol <> $iSearchColPrev _MoveMarker($g_iSearchCol) ; Search column will be selected below, after ContinueCase $iSearchColPrev = $g_iSearchCol Case $sSearchHow <> $sSearchHowPrev $sSearchHowPrev = $sSearchHow Case Else ; no change in both Combo controls (same search column, same search way) ContinueLoop EndSelect ContinueCase Case $g_idEditDummy _GUICtrlHeader_SetItemFormat($g_hHeader, $iSortCol, $HDF_STRING + ($iSortCol > -1 ? $g_aColAligns[$iSortCol] : 0)) $g_sSearch = GUICtrlRead($idEdit) $g_tIndex = $g_tDefaultIndex If $g_sSearch = "" Then ; Empty search string, display all rows $g_aSubArray = $g_aArray $g_iSearch = $g_iRows Else ; Find rows matching the search string $g_iSearch = 0 If $sSearchHow = "Normal search" Then ; all searches use RegEx => escape 12 + 1 metacharacters $g_sSearch = StringRegExpReplace($g_sSearch, "(\\|\.|\^|\$|\||\[|\(|\{|\*|\+|\?|\#|\))" , "\\$1") EndIf ; ConsoleWrite("$sSearchHow = " & $sSearchHow & @TAB & "$g_sSearch = " & $g_sSearch & @lf) If $g_iSearchCol = - 1 Then ; - 1 means search All columns For $i = 0 To $g_iRows - 1 For $j = 0 To $g_iCols - 1 If StringRegExp($g_aArray[$i][$j], "(?i)" & $g_sSearch) Then For $k = 0 To $g_iCols - 1 $g_aSubArray[$g_iSearch][$k] = $g_aArray[$i][$k] Next $g_iSearch += 1 ContinueLoop 2 EndIf Next Next Else ; Search only in 1 column For $i = 0 To $g_iRows - 1 If StringRegExp($g_aArray[$i][$g_iSearchCol], "(?i)" & $g_sSearch) Then For $j = 0 To $g_iCols - 1 $g_aSubArray[$g_iSearch][$j] = $g_aArray[$i][$j] Next $g_iSearch += 1 EndIf Next EndIf ; Delete eventual temporary subindexes For $i = 0 To $g_iCols - 1 If VarGetType($g_aIndexTemp[$i]) = "DLLStruct" Then $g_aIndexTemp[$i] = "" ; "String" Next EndIf GUICtrlSetData($idResult, " " & $g_iSearch & ($g_sSearch = "" ? " rows (no pattern)" : " matching rows")) GUICtrlSendMsg($g_idListView, $LVM_SETITEMCOUNT, $g_iSearch, 0) _GUICtrlListView_SetSelectedColumn($g_hListView, $g_iSearchCol) ; seems ok here (after $LVM_SETITEMCOUNT) Case $g_idListView ; Sort $iSortCol = GUICtrlGetState($g_idListView) If $iSortCol <> $iSortColPrev Then _GUICtrlHeader_SetItemFormat($g_hHeader, $iSortColPrev, $HDF_STRING + ($iSortColPrev > -1 ? $g_aColAligns[$iSortColPrev] : 0)) EndIf ; Set $g_tIndex + eventual update of $g_aIndexTemp[$iSortCol] OR $g_aIndex[$iSortCol] If GUICtrlRead($idEdit) Then _UpdateIndex($g_aIndexTemp, $iSortCol) Else _UpdateIndex($g_aIndex, $iSortCol) EndIf $g_iSortDir = (($iSortCol = $iSortColPrev) ? ($g_iSortDir = $HDF_SORTUP ? $HDF_SORTDOWN : $HDF_SORTUP) : ($HDF_SORTUP)) _GUICtrlHeader_SetItemFormat($g_hHeader, $iSortCol, $HDF_STRING + $g_aColAligns[$iSortCol] + $g_iSortDir) GUICtrlSendMsg($g_idListView, $LVM_SETSELECTEDCOLUMN, $iSortCol, 0) GUICtrlSendMsg($g_idListView, $LVM_SETITEMCOUNT, $g_iSearch, 0) $iSortColPrev = $iSortCol Case $GUI_EVENT_RESTORE ; needed, or Marker goes back in 0, 0 after Restore (why ?) _MoveMarker($g_iSearchCol) EndSwitch WEnd ; Cleanup GUIDelete($g_hGui) EndFunc ;==>Example ;======================================================================== Func WM_DRAWITEM( $hWnd, $iMsg, $wParam, $lParam ) ; Display items in an owner drawn ListView Local Static $tRect = DllStructCreate( $tagRECT ), $pRect = DllStructGetPtr( $tRect ), $tSize = DllStructCreate( $tagSIZE ) Local Static $hBrushYellow = _WinAPI_CreateSolidBrush( 0xFFFF00 ), $hBrushCyan = _WinAPI_CreateSolidBrush( 0x00FFFF ) ; Yellow and cyan, BGR Local Static $hBrushHighLight = _WinAPI_GetSysColorBrush( $COLOR_HIGHLIGHT ), $hBrushButtonFace = _WinAPI_GetSysColorBrush( $COLOR_BTNFACE ) ; We can optimize code by removing Switch statements because the ListView is the only ownerdrawn control and only $ODA_DRAWENTIRE actions are present Local $tDrawItem = DllStructCreate( $tagDRAWITEM, $lParam ), $itemID = DllStructGetData( $tDrawItem, "itemID" ), $iState = DllStructGetData( $tDrawItem, "itemState" ), $hDC = DllStructGetData( $tDrawItem, "hDC" ), $sItemText ; Loop through columns ($i is the column index) For $i = 0 To $g_iCols - 1 ; Subitem rectangle DllStructSetData( $tRect, 2, $i ) ; Top DllStructSetData( $tRect, 1, $LVIR_BOUNDS ) ; Left GUICtrlSendMsg( $g_idListView, $LVM_GETSUBITEMRECT, $itemID, $pRect ) DllStructSetData( $tRect, 1, DllStructGetData( $tRect, 1 ) + 3 ) ; Left margin ; If $i = 0 (first column), the rectangle is calculated for the entire listview item. ; Compensate for this by setting the width of the rectangle to the width of the first column. ; Before that, if item is selected, fill the entire listview item with the highlight background color. If $i = 0 Then If BitAND( $iState, $ODS_SELECTED ) Then DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", $fListViewHasFocus = 1 ? $hBrushHighLight : $hBrushButtonFace ) ; _WinAPI_FillRect DllStructSetData( $tRect, 3, DllStructGetData( $tRect, 1 ) + GUICtrlSendMsg( $g_idListView, $LVM_GETCOLUMNWIDTH, 0, 0 ) ) EndIf ; Retrieve subitem text If $g_iSortDir = 0x0400 Then ; 0x0400 = $HDF_SORTUP $sItemText = $g_aSubArray[$g_tIndex.arr($itemID + 1)][$i] Else $sItemText = $g_aSubArray[$g_tIndex.arr($g_iSearch - $itemID)][$i] EndIf ; Subitem rectangle for right and center aligned columns If $g_aColAligns[$i] = $HDF_RIGHT Or $g_aColAligns[$i] = $HDF_CENTER Then DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 Switch $g_aColAligns[$i] Case $HDF_RIGHT DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Right" ) - DllStructGetData( $tSize, "X" ) - 6 ) Case $HDF_CENTER DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + ( DllStructGetData( $tRect, "Right" ) - DllStructGetData( $tRect, "Left" ) - DllStructGetData( $tSize, "X" ) ) / 2 - 3 ) EndSwitch EndIf ; Subitem text color DllCall( "gdi32.dll", "int", "SetTextColor", "handle", $hDC, "int", BitAND( $iState, $ODS_SELECTED ) ? $fListViewHasFocus = 1 ? 0xFFFFFF : 0x000000 : 0x000000 ) ; _WinAPI_SetTextColor ; Draw subitem text DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sItemText, "int", StringLen( $sItemText ), "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText ; Skip column if search for 1 column only and $i is not the searched column If $g_iSearchCol > - 1 And $i <> $g_iSearchCol Then ContinueLoop ; > - 1 means search for 1 column (0, 1, 2...) ; Mark matching substring if found in this column If $g_sSearch Then Local $sMatch = StringRegExp( $sItemText, "(?i)" & $g_sSearch, 1 ) If Not @error Then ; match found Local $extended = @extended, $iLen = StringLen( $sMatch[0] ) ; Rectangle for matching substring DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sItemText, "int", $extended - $iLen - 1, "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + DllStructGetData( $tSize, "X" ) ) DllCall( "gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sMatch[0], "int", $iLen, "struct*", $tSize ) ; _WinAPI_GetTextExtentPoint32 DllStructSetData( $tRect, "Right", DllStructGetData( $tRect, "Left" ) + DllStructGetData( $tSize, "X" ) ) ; Fill rectangle with yellow or cyan (selected) background color DllStructSetData( $tRect, 2, DllStructGetData( $tRect, 2 ) + 1 ) ; Top margin DllCall( "user32.dll", "int", "FillRect", "handle", $hDC, "struct*", $tRect, "handle", BitAND( $iState, $ODS_SELECTED ) ? $hBrushCyan : $hBrushYellow ) ; _WinAPI_FillRect ; Draw matching substring in rectangle DllStructSetData( $tRect, 2, DllStructGetData( $tRect, 2 ) - 1 ) ; Top margin DllCall( "gdi32.dll", "int", "SetTextColor", "handle", $hDC, "int", 0x000000 ) ; _WinAPI_SetTextColor DllCall( "user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sMatch[0], "int", $iLen, "struct*", $tRect, "uint", 0 ) ; _WinAPI_DrawText EndIf EndIf Next Return $GUI_RUNDEFMSG #forceref $hWnd, $iMsg, $wParam EndFunc ;======================================================================== Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Switch HWnd(DllStructGetData($tNMHEADER, "hWndFrom")) Case $g_hHeader Local $iCode = DllStructGetData($tNMHEADER, "Code") Switch $iCode Case $NM_RCLICK Local $aHit = _GUICtrlListView_SubItemHitTest($g_hListView) ; $aHit[1] : 0-based index of the LV subitem... i.e. the column in our case (may be -1 if right click on empty part of header) If $aHit[1] > - 1 Then ; valid column GUICtrlSetData($g_idComboCol, $aHit[1]) GUICtrlSendToDummy($g_idComboColDummy) EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY ;======================================================================== Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) Local $hWndFrom = $lParam Local $iCode = BitShift($wParam, 16) ; High word Switch $hWndFrom Case $g_hEdit Switch $iCode Case $EN_CHANGE GUICtrlSendToDummy($g_idEditDummy) EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND ;======================================================================== Func _Generate_All(ByRef $g_aArray) ConsoleWrite("$g_iRows = " & $g_iRows & " $g_iCols = " & $g_iCols & @CRLF) Local $hTimer = TimerInit() $g_aArray = FAS_Random2DArrayAu3($g_iRows, "sifdtr", "abcdefghijklmnopqrstuvwxyz") ; $g_aArray = FAS_Random2DArrayAu3($g_iRows, "sifdtr", "abcdefghijklmnopqrstuvwxyz" & "\.^$|[({*+?#)") ; 12 + 1 RegEx metacharacters For $i = 0 To $g_iRows - 1 $g_tIndex.arr($i + 1) = $i Next ConsoleWrite("Generating array & one index = " & TimerDiff($hTimer) & @CRLF & @CRLF) EndFunc ;==>_Generate_All ;======================================================================== Func _SortArrayStruct(Const ByRef $aArray, $iCol, $iRows) Local $tIndex = DllStructCreate("uint arr[" & $iRows & "]") Local $pIndex = DllStructGetPtr($tIndex) Local Static $hDll = DllOpen("kernel32.dll") Local Static $hDllComp = DllOpen("shlwapi.dll") Local $lo, $hi, $mi, $r ; Sorting by one column For $i = 1 To $iRows - 1 $lo = 0 $hi = $i - 1 Do $mi = Int(($lo + $hi) / 2) $r = DllCall($hDllComp, 'int', 'StrCmpLogicalW', 'wstr', $aArray[$i][$iCol], 'wstr', $aArray[DllStructGetData($tIndex, 1, $mi + 1)][$iCol])[0] 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 ;==>_SortArrayStruct ;======================================================================== Func _UpdateIndex(ByRef $aIndex, $iCol) If VarGetType($aIndex[$iCol]) = "DLLStruct" Then $g_tIndex = $aIndex[$iCol] Else $g_tIndex = _SortArrayStruct($g_aSubArray, $iCol, $g_iSearch) $aIndex[$iCol] = $g_tIndex ; "DLLStruct" (or "Int32" when no match found +++) EndIf EndFunc ;==>_UpdateIndex ;======================================================================== Func _MoveMarker($iCol) If $iCol = - 1 Then ; All columns ControlMove($g_hGui, "", $g_idMarker, 10, 40 - 3, 630, 3) ; 10 / 40 / 630 are LV coords Else ; 1 column (0, 1, 2...) Local $aRect = _GUICtrlHeader_GetItemRect($g_hHeader, $iCol) ControlMove($g_hGui, "", $g_idMarker, 10 + $aRect[0], 40 - 3, $aRect[2] - $aRect[0] + 1, 3) EndIf EndFunc ;==>_MoveMarker You should be able to combine the present functionalities with $NM_CUSTOMDRAW instead of $WM_DRAWITEM, not forgetting the special context menu found in this thread, and not forgetting Norm73's wish to immediately scroll on 1st match, for example like in the pic below (2 first non-matching lines left visible on purpose) . The pic below is not a script, it's just the way it could appear : @Norm73 unfortunately _GUICtrlListView_EnsureVisible (as indicated in one of your last post) isn't enough to do what you want. It sometimes display the requested item at the bottom of the screen (if you were selecting an item placed below it) LVM_GETTOPINDEX is useful to retrieve the index of the topmost visible item, but unfortunately there is no "LVM_SETTOPINDEX" to force an item to be placed at topmost position. After some searches here & there, I tested a way that can do it and it seems to work fine. Here is the code in case anyone is interested : ;~ ; It works !!! ;~ Local $iRow1stMatch = 200 ;~ Local $iGetTopIndex = _GUICtrlListView_GetTopIndex($g_idListView) ;~ Local $iGetItemSpacingY = _GUICtrlListView_GetItemSpacingY($g_idListView, True) ; only once ;~ _GUICtrlListView_Scroll($g_idListView, 0, ($iRow1stMatch - $iGetTopIndex) * $iGetItemSpacingY) Now it's time to rest, no more AutoIt during several days. Good luck guys and see you one of these days1 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