Leaderboard
Popular Content
Showing content with the highest reputation on 09/25/2017 in all areas
-
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.7z2 points
-
youtuber, Do not be so impatient - some of us have more important things to do. This works for me: #include <GUIConstantsEx.au3> $Form1 = GUICreate("Unescape Decoder and Encoder", 876, 422, 192, 124) $Edit1 = GUICtrlCreateEdit("AutoitTest", 48, 48, 337, 305) $Edit2 = GUICtrlCreateEdit("", 412, 49, 425, 305) $Label1 = GUICtrlCreateLabel("String", 56, 24, 50, 17) $Label2 = GUICtrlCreateLabel("Unescape", 416, 24, 50, 17) $ButtonEncoder = GUICtrlCreateButton("Encoder", 150, 376, 147, 25) $ButtonDecoder = GUICtrlCreateButton("Decoder", 550, 376, 147, 25) GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $ButtonEncoder $sBinary = StringTrimLeft(StringToBinary(GUICtrlRead($Edit1)), 2) $sEscaped = StringRegExpReplace($sBinary, "(.{2})", "%$1") GUICtrlSetData($Edit2, $sEscaped) GUICtrlSetData($Edit1, "") Case $ButtonDecoder $sEncoded = GUICtrlRead($Edit2) $sStripped = StringReplace($sEncoded, "%", "") ConsoleWrite($sStripped & @CRLF) $sDecoded = BinaryToString("0x" & $sStripped) ConsoleWrite($sDecoded & @CRLF) GUICtrlSetData($Edit1, $sDecoded) EndSwitch WEnd M231 point
-
youtuber, It is a simple ASCII conversion: #include <MsgBoxConstants.au3> $sString = "AutoIt" $sCoded = StringTrimLeft(StringToBinary($sString), 2) MsgBox($MB_SYSTEMMODAL, "Encoded", $sCoded) $sDecoded = BinaryToString("0x" & $sCoded) MsgBox($MB_SYSTEMMODAL, "Decoded", $sDecoded) M231 point
-
Couple of things: You aren't showing the whole script as you have a call to a FUNC that isn't shown: Call ("Ajde") Don't use Call() but simply do : VelikiOdmor() You aren't testing for the success of the _FileListToArrayRec() and assume there is an Array with at least 2 places. Check for the @Error & [0] to know the number of files returned. There are a couple of other warnings when ran through au3check. Jos1 point
-
[BUGFIX VERSION] - 25 Sep 17 Fixed: A small bug which only appeared if you were continually emptying a ListView with _GUICtrlListView_DeleteAllItems, which means you need to use _GUIListViewEx_Close and then _GUIListViewEx_Init to reset the UDF. The closed handle was not being deleted correctly which meant that any actions on the reinitialised ListView were likely to fail as the UDF looked at the old data. Apologies. New UDF in the first post. M231 point
-
How on earth do we add a string on EVERY OTHER line of a text file ?
asiawatcher reacted to Malkey for a topic
Using _ReplaceStringInFile() as did KickStarter15 in post #9, there is this example. #include <file.au3> ; ----Create file ------------ Local $sFilePath = @ScriptDir & "\IP.txt" Local $hFileOpen = FileOpen($sFilePath, 10) ; $FO_OVERWRITE (2) = Write mode (erase previous contents) + $FO_CREATEPATH (8) = Create directory structure if it doesn't exist. FileWrite($hFileOpen, StringRegExpReplace(FileRead(@ScriptFullPath), "(?s)^.*#cs\v+|\v+#ce.*$", "")) ; Get block comment from this script and write to file. FileClose($hFileOpen) ConsoleWrite(" -------- before -------------" & @CRLF & FileRead($sFilePath) & @CRLF) _ReplaceStringInFile($sFilePath,@CR, "") ; All Carriage Return + Line Feeds will become Line Feeds only. ; If you know for certain that only @CRLF are used in the file then you can eliminate the previous _ReplaceStringInFile() and in the next ; _ReplaceStringInFile() change the two @LF's to @CRLF's. _ReplaceStringInFile($sFilePath, "#EXTINF:12.0" & @LF, "#EXTINF:12.0" & @LF & "http://" & @IPAddress1 & "/") ConsoleWrite(" -------- after --------------" & @CRLF & FileRead($sFilePath) & @CRLF) FileDelete($sFilePath) #cs #EXTM3U #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:5448549 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448549.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006834126320-12006835068012 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448550.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006835068012-12006836991064 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448551.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006836991064-12006838592636 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448552.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006838592636-12006839630396 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448553.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006839630396-12006840960308 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448554.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006840960308-12006842139632 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448555.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006842139632-12006843484584 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448556.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006843484584-12006845024868 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448557.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006845024868-12006847775684 #EXTINF:12.0 C8B6E0C508FC74915BAA94D116F142165-frag5448558.ts?token=822259&gid=C8B6E0C508FC74915BAA94D116F142165&range=12006847775684-12006850449984 #ce1 point -
Require Admin Design
RC86 reacted to JLogan3o13 for a topic
@RC86 Directives like #RequireAdmin are not conditional; AutoIt looks for them and executes before running the script. You can use something like _Security_CreateProcessWithToken (check the help file) as a work around. It actually does the opposite; you run your script elevated and this allows you to create a process that is non-elevated. Also, there are a couple of folks who have done some work on elevating and reducing rights on demand using UAC. Check out the thread below for some of the work done my Kafu and Ascend4nt1 point -
What about the option in the group policy? gpedit.msc1 point
-
Layanor, Welcome to the AutoIt forums. We used to accept gaming scripts, but found gamers to be a nightmare to moderate - so the rules became stricter and stricter until we ended up with the current, some would say draconian, state of not allowing any form of game-related thread at all. The fact you are a game developer is entirely moot. Essentially: "Yes". Our forum, our rules. M231 point
-
This was he first one I found: https://social.msdn.microsoft.com/Forums/en-US/39eb7cf4-2e85-4010-8e6a-10da20b352f7/replacing-changing-the-pictures-in-powerpoint-presentation?forum=isvvba I notice in this example it's not doing a straight swap, but it is capturing properties (specifically location and size) and re-assigning them to the new image. What properties are you talking about?1 point
-
How on earth do we add a string on EVERY OTHER line of a text file ?
asiawatcher reacted to KickStarter15 for a topic
@asiawatcher, You can play with this. #include <file.au3> $sFilePath = @ScriptDir & "\IP.ini" Local $hFileOpen = FileOpen($sFilePath) If $hFileOpen = -1 Then MsgBox($MB_SYSTEMMODAL, "", "An error occurred opening file.") Exit EndIf $string = _ReplaceStringInFile (@ScriptDir & "\IP.ini", "#EXTINF:12.0", "#EXTINF:12.0"&@CRLF&"http://"&@IPAddress1&"/") StringReplace($string, @CRLF, "") FileClose($hFileOpen)1 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 -
Using Xpdf tools : ; #FUNCTION# ==================================================================================================================== ; Name...........: _XFDF_Info ; Description....: Retrives informations from a PDF file ; Syntax.........: _XFDF_Info ( "File" [, "Info"] ) ; Parameters.....: File - PDF File. ; Info - The information to retrieve ; Return values..: Success - If the Info parameter is not empty, returns the desired information for the specified Info parameter ; - If the Info parameter is empty, returns an array with all available informations ; Failure - 0, and sets @error to : ; 1 - PDF File not found ; 2 - Unable to find the external programm ; Remarks........: The array returned is two-dimensional and is made up as follows: ; $array[1][0] = Label of the first information (title, author, pages...) ; $array[1][1] = value of the first information ; ... ; =============================================================================================================================== Func _XFDF_Info($sPDFFile, $sInfo = "") Local $sXPDFInfo = @ScriptDir & "\pdfinfo.exe" If NOT FileExists($sPDFFile) Then Return SetError(1, 0, 0) If NOT FileExists($sXPDFInfo) Then Return SetError(2, 0, 0) Local $iPid = Run(@ComSpec & ' /c "' & $sXPDFInfo & ' "' & $sPDFFile & '"', @ScriptDir, @SW_HIDE, 2) Local $sResult While 1 $sResult &= StdoutRead($iPid) If @error Then ExitLoop WEnd Local $aInfos = StringRegExp($sResult, "(?m)^(.*?): +(.*)$", 3) If Mod( UBound($aInfos, 1), 2) = 1 Then Return SetError(3, 0, 0) Local $aResult [ UBound($aInfos, 1) / 2][2] For $i = 0 To UBound($aInfos) - 1 Step 2 If $sInfo <> "" AND $aInfos[$i] = $sInfo Then Return $aInfos[$i + 1] $aResult[$i / 2][0] = $aInfos[$i] $aResult[$i / 2][1] = $aInfos[$i + 1] Next If $sInfo <> "" Then Return "" Return $aResult EndFunc ; ---> _XFDF_Info ; #FUNCTION# ==================================================================================================================== ; Name...........: _XPDF_Search ; Description....: Retrives informations from a PDF file ; Syntax.........: _XFDF_Info ( "File" [, "String" [, Case = 0 [, Flag = 0 [, FirstPage = 1 [, LastPage = 0]]]]] ) ; Parameters.....: File - PDF File. ; String - String to search for ; Case - If set to 1, search is case sensitive (default is 0) ; Flag - A number to indicate how the function behaves. See below for details. The default is 0. ; FirstPage - First page to convert (default is 1) ; LastPage - Last page to convert (default is 0 = last page of the document) ; Return values..: Success - ; Flag = 0 - Returns 1 if the search string was found, or 0 if not ; Flag = 1 - Returns the number of occcurrences found in the whole PDF File ; Flag = 2 - Returns an array containing the number of occurrences found for each page ; (only pages containing the search string are returned) ; $array[0][0] - Number of matching pages ; $array[0][1] - Number of occcurrences found in the whole PDF File ; $array[n][0] - Page number ; $array[n][1] - Number of occcurrences found for the page ; Failure - 0, and sets @error to : ; 1 - PDF File not found ; 2 - Unable to find the external programm ; =============================================================================================================================== Func _XPDF_Search($sPDFFile, $sSearch, $iCase = 0, $iFlag = 0, $iStart = 1, $iEnd = 0) Local $sXPDFToText = @ScriptDir & "\pdftotext.exe" Local $sOptions = " -layout -f " & $iStart Local $iCount = 0, $aResult[1][2] = [[0, 0]], $aSearch, $sContent, $iPageOccCount If NOT FileExists($sPDFFile) Then Return SetError(1, 0, 0) If NOT FileExists($sXPDFToText) Then Return SetError(2, 0, 0) If $iEnd > 0 Then $sOptions &= " -l " & $iEnd Local $iPid = Run($sXPDFToText & $sOptions & ' "' & $sPDFFile & '" -', @ScriptDir, @SW_HIDE, 2) While 1 $sContent &= StdoutRead($iPid) If @error Then ExitLoop WEnd Local $aPages = StringSplit($sContent, chr(12) ) For $i = 1 To $aPages[0] $iPageOccCount = 0 While StringInStr($aPages[$i], $sSearch, $iCase, $iPageOccCount + 1) If $iFlag <> 1 AND $iFlag <> 2 Then $aResult[0][1] = 1 ExitLoop EndIf $iPageOccCount += 1 WEnd If $iPageOccCount Then Redim $aResult[ UBound($aResult, 1) + 1][2] $aResult[0][1] += $iPageOccCount $aResult[0][0] = UBound($aResult) - 1 $aResult[ UBound($aResult, 1) - 1 ][0] = $i + $iStart - 1 $aResult[ UBound($aResult, 1) - 1 ][1] = $iPageOccCount EndIf Next If $iFlag = 2 Then Return $aResult Return $aResult[0][1] EndFunc ; ---> _XPDF_Search ; #FUNCTION# ==================================================================================================================== ; Name...........: _XPDF_ToText ; Description....: Converts a PDF file to plain text. ; Syntax.........: _XPDF_ToText ( "PDFFile" , "TxtFile" [ , FirstPage [, LastPage [, Layout ]]] ) ; Parameters.....: PDFFile - PDF Input File. ; TxtFile - Plain text file to convert to ; FirstPage - First page to convert (default is 1) ; LastPage - Last page to convert (default is last page of the document) ; Layout - If true, maintains (as best as possible) the original physical layout of the text ; If false, the behavior is to 'undo' physical layout (columns, hyphenation, etc.) ; and output the text in reading order. ; Default is True ; Return values..: Success - 1 ; Failure - 0, and sets @error to : ; 1 - PDF File not found ; 2 - Unable to find the external program ; =============================================================================================================================== Func _XPDF_ToText($sPDFFile, $sTXTFile, $iFirstPage = 1, $iLastPage = 0, $bLayout = True) Local $sXPDFToText = @ScriptDir & "\pdftotext.exe" Local $sOptions If NOT FileExists($sPDFFile) Then Return SetError(1, 0, 0) If NOT FileExists($sXPDFToText) Then Return SetError(2, 0, 0) If $iFirstPage <> 1 Then $sOptions &= " -f " & $iFirstPage If $iLastPage <> 0 Then $sOptions &= " -l " & $iLastPage If $bLayout = True Then $sOptions &= " -layout" Local $iReturn = ShellExecuteWait ( $sXPDFToText , $sOptions & ' "' & $sPDFFile & '" "' & $sTXTFile & '"', @ScriptDir, "", @SW_HIDE) If $iReturn = 0 Then Return 1 Return 0 EndFunc ; ---> _XPDF_ToText1 point
-
DigDeep, Adding the Application2 file as an include places that code in the Parent Application file at the point of the #include line. So all the code in that file is parsed before any of the code in the parent - hence you are calling the GUI2 function in the App2 file to create a button in a non-existent GUI. I have modified the files so that they work as you wish - please read the comments I have added: Parent Application.au3 Application2.au3 Note the requirement to put a placeholder value in the $Button2 variable - if you set it to 0 or leave it undeclared then the Case will file immediately you enter the idle loop as GUIGetMsg returns 0 as the default when no event has occurred. Please ask if you have any further questions. M231 point
-
Caveat: I can't run your code due to priv restrictions where I am. It would be a lot easier if you built 1 array of the updates you have available and 1 array of the updates you would like to hide and made a simple standalone example. The logic of the $j loop appears in error: For each item in $Hideup you are going to test your update and remove it if it matches and exit loop, but for each item in $Hideup you don't match to you are going to add it to your download list... surely you only want to add it once and only if no matches occur? Equally if you don't match the first one, you will add it, only to then remove it later... Pseudo code $I loop $match = false For $j = 0 To UBound($Hideup) -1 if in list {$match = true, exitloop} Next <---- finish the loop first if $match = false {add to list to download} <---- conditional dependent upon the completed check of $Hideup next $I1 point
-
Version 2.0.0
1,034 downloads
On one/multiple big sheet(s) you get users (columns) and groups (rows). The list is sorted descending by number of members so you get the users with most groups and the groups with most members on top of the page. You can filter by (multiple) samaccountname(s), department or you can create your own LDAP query filter. You can filter the resulting list of groups using a Regular Expression. Version 2.0 uses maps so at the moment it requires the latest beta version of AutoIt! BTW: If you like this tool please click the "I like this" button. This tells me where to next put my development effort1 point -
Hello, this is my first release of UDF for AutoIt. This UDF is designed for work with Unicode string, so only use it with AutoIt3.exe (Unicode Version). I have used it on my project for unicode URL Encoding and Decoding. This is an example project that used this UDF: http://dhilip89.hopto.org/autoit%20test/li.../unicode%20test #include-once ;=============================================================================== ; _UnicodeURLEncode() ; Description: : Encodes an unicode string to be URL-friendly ; Parameter(s): : $UnicodeURL - The Unicode String to Encode ; Return Value(s): : The URL encoded string ; Author(s): : Dhilip89 ; Note(s): : - ; ;=============================================================================== Func _UnicodeURLEncode($UnicodeURL) $UnicodeBinary = StringToBinary ($UnicodeURL, 4) $UnicodeBinary2 = StringReplace($UnicodeBinary, '0x', '', 1) $UnicodeBinaryLength = StringLen($UnicodeBinary2) Local $EncodedString For $i = 1 To $UnicodeBinaryLength Step 2 $UnicodeBinaryChar = StringMid($UnicodeBinary2, $i, 2) If StringInStr("$-_.+!*'(),;/?:@=&abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", BinaryToString ('0x' & $UnicodeBinaryChar, 4)) Then $EncodedString &= BinaryToString ('0x' & $UnicodeBinaryChar) Else $EncodedString &= '%' & $UnicodeBinaryChar EndIf Next Return $EncodedString EndFunc ;==>_UnicodeURLEncode ;=============================================================================== ; _UnicodeURLDecode() ; Description: : Tranlates a URL-friendly string to a normal string ; Parameter(s): : $toDecode - The URL-friendly string to decode ; Return Value(s): : The URL decoded string ; Author(s): : nfwu, Dhilip89 ; Note(s): : Modified from _URLDecode() that's only support non-unicode. ; ;=============================================================================== Func _UnicodeURLDecode($toDecode) Local $strChar = "", $iOne, $iTwo Local $aryHex = StringSplit($toDecode, "") For $i = 1 To $aryHex[0] If $aryHex[$i] = "%" Then $i = $i + 1 $iOne = $aryHex[$i] $i = $i + 1 $iTwo = $aryHex[$i] $strChar = $strChar & Chr(Dec($iOne & $iTwo)) Else $strChar = $strChar & $aryHex[$i] EndIf Next $Process = StringToBinary (StringReplace($strChar, "+", " ")) $DecodedString = BinaryToString ($Process, 4) Return $DecodedString EndFunc ;==>_UnicodeURLDecode #endregion1 point
-
I have a load of Excel spreadsheets with VBA code attached, and I want to update them all to the latest version of the VBA code. AutoIt seems like the tool for the job. Has anyone done anything like this before? I'm thinking like this... 1. Place the new version of the VBA code in the clipboard 2. Open the .xls to be updated 3. Run the AutoIt script which... 3a. Sends Alt-F11 to open the VBA macro editor 3b. Switches between the code windows, attempting to work out which window contains the module that is being updated 3c. Select all and paste clipboard contents 3d. Close the VBA macro editor 4. Save and close 3b is probably the hardest step. I could include snippets of the old version(s) in the new code and search for these. Ideally I would have some kind of structured header, but I don't have that right now and I want to update the code in several dozen spreadsheets.1 point
-
You should update (see under help) at least to 7.0.9. However, with an embeded object like Reader and some other -direct with dll or indirect with IE - you get a repain problem. There has been a discussion here about this, but no solution. So I start it direct and move it to the position and size I want and influence the Reader direct. HTH, Reinhard1 point
-
Does this IE based solution work for you? #include <GUIConstants.au3> $Form1 = GUICreate("Browse PDF", 400,300,400,300) $Obj = ObjCreate("Shell.Explorer.2") $browser = GUICtrlCreateObj($Obj, 0, 0, 400, 300) GUISetState(@SW_SHOW) $Obj.Navigate('C:\Program Files\Adobe\Acrobat 7.0\Help\ENU\Reader.pdf') ;; $Obj.Navigate('C:\Programme\Adobe\Acrobat 7.0\Help\ENU\Reader.pdf') While 1 $msg = GuiGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case Else ;;;;;;; EndSelect WEnd Exit1 point
-
Which Acrobat/Reader version (exact) you work with. Can you show your code-snippet you work with. br, reinhard1 point
-
I don't know what the problem is, but what happens if you type: "C:\Program Files\Adobe\Acrobat 7.0\Help\ENU\Reader.pdf" into the IE address line. Reinhard1 point
-
Also with Acrobat/Reader 7 and higher you get this error message if the viewer is not configured to show the PDF in (IE) Browser, what normally is set as standard. Under "Edit" choose "BasicSetting" (last menuitem), select "Internet" and then mark [x] PDF in Viewer (MenuItem Free translated from a german version). For scripter this means, if you want to make shure that "embedded" works, you first have to check/influence the registry key. HTH, Reinhard1 point
-
Works with Acrobat and Reader (versions >= 7). Will be installed from both apps. br, Reinhard1 point
-
If I remember right you need a Version >= 7 (Acrobat or Reader). HTH, Reinhard PS: By the way you shouldn't use .. = $oPDF.GetVersions. Adobe will discontinue, but in actual versions it works.1 point