Leaderboard
Popular Content
Showing content with the highest reputation on 09/24/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.7z4 points
-
DotNet.au3 UDF to access .NET Framework from AutoIt
stevepresley reacted to LarsJ for a topic
.NET Common Language Runtime (CLR) Framework was published five months ago. CLR.au3 which is the main UDF makes it possible to execute .NET code directly in an AutoIt script. .NET code in this context should be perceived in a very broad sense. As shown in the examples, there are virtually no limits to the possibilities that the UDF opens up for. .NET Common Language Runtime (CLR) Framework is the result of the work in Using .NET libary with AutoIt, possible? CLR.au3 is implemented in this thread. Most of the code in CLR.au3 is a translation of CLR.ahk from .NET Framework Interop (CLR, C#, VB) in the AutoHotkey forum. DotNet.au3 is a complete translation of CLR.ahk. This example is about DotNet.au3. It contains information about the functions in the UDF. Usage of the functions is demonstrated through small examples. And there is a description of a few .NET Framework concepts. The AutoHotkey project The AutoHotkey project started in .NET Framework Interop in autumn 2009. The latest update of CLR.ahk in .NET Framework Interop (CLR, C#, VB) was november 2011. The whole project seems to have been developed over this 3-year period. The project was developed by Lexikos in the AutoHotkey forum. He certainly looks very knowledgeable about the code in the .Net Framework and he has done a great job in implementing the AutoHotkey code in CLR.ahk. Lots of credit to Lexikos. If you want to test the AutoHotkey code, you can find a recipe here. DotNet.au3 Because a lot of COM support is included internally in AutoHotkey and especially because AutoHotkey natively supports safearrays, the code in CLR.ahk is short and compact. 150 code lines. In the zip-file below AutoIt safearray support is implemented in two separate UDFs: SafeArray.au3 and AccVarsUtilities.au3. Both of these UDFs were started in Accessing AutoIt Variables. That way, it has also been possible to keep the code in DotNet.au3 short and compact. 190 code lines. You should take a look at DotNet.au3. It's nice and easily readable code (maybe not so easy to understand, but easy to read). 7 functions DotNet.au3 contains 7 functions and 2 internal functions. The first 3 functions DotNet_Start(), DotNet_StartDomain() and DotNet_StopDomain() are only used to optimize the .NET Framework host (more about .NET concepts below). If you are satisfied with the default .NET Framework host, you can completely skip these functions. The next 3 functions DotNet_LoadAssembly(), DotNet_LoadCScode() and DotNet_LoadVBcode() are used to load .NET code into a domain. Before it's possible to execute .NET code it must be loaded into a domain. If DotNet_Start() and DotNet_StartDomain() have not been called, DotNet_Start() is called automatically by the 3 functions and the default domain is used to execute .NET code. DotNet_LoadAssembly() loads .NET code in a .NET assembly DLL-file into a domain. The other functions compiles C# and VB source code on the fly, creates a .NET assembly DLL-file in memory and loads the assembly file into a domain. All 3 functions returns a .NET code object which is a reference to the .NET code. The last function DotNet_CreateObject() takes a .NET code object and a class name as input parameters and creates an object as an instance of the class. The class must be defined in the .NET code. Because .NET code is object-oriented code, everything is performed through objects. Now the methods of the object can be called and this executes the functions in the .NET code. Below is a brief description of the 7 functions. $oRuntimeHost = DotNet_Start( $sVersion = "" ) DotNet_Start() Loads the .NET Framework code-execution environment known as the CLR into the AutoIt process and returns a .NET runtime host (a .NET Framework host). Default is to use the latest version of .NET Framework installed on the PC. Specify $sVersion eg. "v2.0.50727" to use an older version of .NET Framework. DotNet_Start() is automatically called by the other functions in DotNet.au3. You only need to call DotNet_Start() if you want to use an older version of .NET Framework. @error = 1 indicates that DotNet_Start() has failed. DotNet_StartDomain( ByRef $oAppDomain, $sFriendlyName = "", $sBaseDirectory = "" ) Creates and starts a user domain to run .NET code. Several user domains can be created and started at the same time. $oAppDomain is the returned domain object. $sFriendlyName is a name to identify the domain. $sBaseDirectory is the base directory where from .NET assemblies are loaded into the domain. The only purpose of $sFriendlyName is to be able to recognize the domain when the domains are listed with DotNet_ListDomains(). DotNet_ListDomains() is a utility function implemented in DotNetUtils.au3. The purpose of $sBaseDirectory is to be able to specify the directory where .NET assemblies are stored. The usage of $sBaseDirectory is demonstrated in examples. A default domain is automatically created by the other functions in DotNet.au3. You only need to call DotNet_StartDomain() if you want to specify a base directory for the domain. DotNet_StopDomain( ByRef $oAppDomain ) Unloads .NET assemblies loaded into the user domain and stops the domain. $oAppDomain is the domain object. The default domain cannot be stopped. $oNetCode = DotNet_LoadAssembly( $sAssemblyName, $oAppDomain = 0 ) DotNet_LoadAssembly() loads .NET code in a .NET assembly DLL-file into a domain and returns a .NET code object (a reference to the .NET code). $sAssemblyName is the name of the assembly DLL-file. $oAppDomain is the user domain. If no user domain is specified the assembly is loaded into the default domain. @error = 2 indicates that DotNet_LoadAssembly() has failed. $oNetCode = DotNet_LoadCScode( $sCode, $sReferences = "", $oAppDomain = 0, $sFileName = "", $sCompilerOptions = "" ) $oNetCode = DotNet_LoadVBcode( $sCode, $sReferences = "", $oAppDomain = 0, $sFileName = "", $sCompilerOptions = "" ) DotNet_LoadCScode() and DotNet_LoadVBcode() compiles C# and VB source code on the fly, creates a .NET assembly DLL-file in memory, loads the assembly file into a domain and returns a .NET code object. $sCode is the C# or VB source code. $sReferences is a pipe (|) delimited list of .NET DLL assemblies that the C#/VB code requires. Eg. "System.dll" or "System.Windows.Forms.dll". $oAppDomain is the user domain. If no user domain is specified the code is loaded into the default domain. The other parameters are related to the compilation process. If $sFileName is the name of a DLL-file the code is compiled into a .NET assembly DLL-file. Else the code is compiled in memory. $sCompilerOptions is rarely used. See Microsoft documentation for details. @error = 3/4 indicates that DotNet_LoadCScode() or DotNet_LoadVBcode() has failed. @error = 5 indicates a syntax error in the C# or VB source code. Such an error can be corrected by correcting the error in the source code. $oObject = DotNet_CreateObject( ByRef $oNetCode, $sClassName, $v3 = Default, ..., $v9 = Default ) DotNet_CreateObject() creates an object as an instance of a class. $oNetCode is a .NET code object as returned by one of the functions DotNet_LoadAssembly(), DotNet_LoadCScode() or DotNet_LoadVBcode(). $sClassName is the name of a class defined in the .NET code. The other parameters depends on the specific class. Summary Two functions must be called to execute .NET code directly in an AutoIt script. One of the functions DotNet_LoadAssembly(), DotNet_LoadCScode() or DotNet_LoadVBcode() to load the .NET code into a domain. And DotNet_CreateObject() to create an object from a class defined in the .NET code. Now the functions in the .NET code can be executed by calling the methods of the object. .NET concepts The .NET CLR In more or less the same way as AutoIt3.exe or AutoIt3_x64.exe is needed to run AutoIt code, the .NET CLR (Common Language Runtime) or the .NET Framework code-execution environment is needed to run .NET code. To be able to run .NET code inside an AutoIt script, the CLR or the .NET Framework code-execution environment must be loaded into the AutoIt process. This is the purpose of DotNet_Start(). The CLR can be loaded into a process through several of the functions in MSCorEE.dll. CorBindToRuntimeEx is one of these functions. DotNet_Start() executes CorBindToRuntimeEx in MSCorEE.dll and loads the CLR into the AutoIt process. A program or a part of a program which is able to start the CLR and execute .NET code is referred to as a .NET runtime host, a CLR host or simply a .NET Framework host. The code in DotNet.au3 implements an AutoIt .NET Framework host. Managed/unmanaged code .NET code which is executed (or managed) through the functions in the CLR is referred to as managed code. C# and VB code is managed code. Code which is not executed through the functions in the CLR is referred to as unmanaged code. AutoIt code is unmanaged code. You usually only distinguish between managed/unmanaged code in relation to .NET code and the .NET Framework. When you are executing .NET code there is often a part of both unmanaged and managed code involved. If you are executing .NET code through AutoIt, the AutoIt code is the unmanaged code and the .NET code is the managed code. The functions in MSCorEE.dll are some of the functions which belongs to the .NET Framework that can be executed from unmanaged code eg. AutoIt code. That's the reason why these functions are used to start the .NET Framework. The COM interfaces _AppDomain, _Assembly and _Type in Interfaces.au3 are some of the interfaces which belongs to the .NET Framework that can be used in unmanaged code. That's the reason why these interfaces are used to implement the functions in DotNet.au3. Managed code like C# cannot be translated into unmanaged code like AutoIt. There is no way to translate a command like "using System;" from C# to AutoIt. In many situations you can implement the same code in AutoIt as you can in C#. But that's generally not a simple translation of the C# code. It's a new implementation of the code. .NET domains With the functions in DotNet.au3 you can create an AutoIt .NET Framework host as shown in this picture: The blue box illustrates the unmanaged AutoIt code which is used to start the .NET Framework and load the CLR into the AutoIt process. The red box illustrates the default domain and several user domains where the managed .NET code is executed. Managed .NET code is always executed within a domain. The purpose of DotNet_StartDomain() and DotNet_StopDomain() is to create, start and stop user domains. If DotNet_StartDomain() isn't called the default domain is used. A domain in managed code is equivalent to a process in unmanaged code. The purpose of domains is to prevent that a crash in one part of the .NET code should lead to a crash in all of the .NET code. A crash of the code in a domain makes the domain inapplicable and a new domain must be created with DotNet_StartDomain(). This is very similar to the way that code is executed in separate processes in the operating system. The purpose of executing code in separate processes is (among other things) to prevent that a crash of the code in one process should lead to a crash of the code in several processes and finally to a crash of the entire operating system. A crash of the code in the default domain makes the entire CLR, that's loaded into the AutoIt process inapplicable. Because it's only possible to load the CLR into the same process once, the only way to reload the CLR is to restart the entire AutoIt process. That is to stop and start the AutoIt script. Usually it does not matter if the default domain or a user domain is used to execute .NET code. It's only strictly necessary to create a user domain if there is a need to specify a base directory for .NET assemblies. The only way to specify a base directory is through DotNet_StartDomain(). .NET assemblies Before it's possible to execute .NET code in a domain, the code must be loaded into the domain. Code is always loaded into a domain through a .NET assembly. This is also the case when .NET code is created on the fly by compiling C# or VB code in memory. Then the .NET code is stored in a .NET assembly which is created in memory and therefrom loaded into the domain. The purpose of DotNet_LoadAssembly() is to load .NET code in a .NET assembly DLL-file into a domain. Either the default domain or a user domain. The purpose of DotNet_LoadCScode() and DotNet_LoadVBcode() is to compile C# and VB code on the fly, create a .NET assembly in memory and load the .NET code into a domain. All 3 functions returns a .NET code object which can be used in DotNet_CreateObject() to create .NET objects. When a .NET assembly is stored as a file on disk it's usually stored with a DLL- or an EXE-extension. It contains information about classes, objects, methods, properties, events, datatypes etc. concerning the resources in the assembly. It's a binary file. A .NET assembly DLL-file should not be confused with a standard DLL-file eg. a DLL-file that belongs to the Windows operating system. A .NET assembly DLL-file contains managed code. A standard DLL-file contains unmanaged code. In the same way as there are tools to extract information about the code in a standard DLL-file, there are also tools to extract information about the code in a .NET assembly DLL-file. One of these tools is ILSpy. More about ILSpy in examples section below. .NET objects Because .NET code is object-oriented code, everything is performed through objects, properties and methods. When functions are executed in .NET code, they are executed as object methods. DotNet_CreateObject() takes a .NET code object as returned by DotNet_LoadAssembly(), DotNet_LoadCScode() or DotNet_LoadVBcode() and a class name as input parameters and creates a .NET object as an instance of the class. The class must be defined in the .NET code. Now the methods of the object can be called and this executes the functions in the .NET code. Examples The Examples folder contains scripts to demonstrate the usage of the functions in DotNet.au3. In scripts where .NET code is needed for the demonstration, the code is copied from original AutoHotkey examples: An example with a XPTable.dll .NET assembly (implemented in AutoIt in this post) and two simple C# and VB code examples. I don't want to review all examples. The examples are small examples like this: #include "..\..\Includes\DotNet.au3" Opt( "MustDeclareVars", 1 ) Example() Func Example() ; Start the latest version of .NET Framework ; DotNet_Start() is automatically called by the other functions in DotNet.au3 ; You only have to call DotNet_Start() if you need an older version of .NET Framework DotNet_Start() If @error Then Return ConsoleWrite( "DotNet_Start ERR" & @CRLF ) ConsoleWrite( "DotNet_Start OK" & @CRLF ) EndFunc The example simply starts the .NET Framework from an AutoIt script. Run the examples in SciTE by pressing F5 on the keyboard. A few examples with "(compile me)" in the file name must be compiled. Run these examples by double-clicking the exe-file. ILSpy .NET assembly browser ILSpy is an open-source .NET assembly browser. Download ILSpy_Master_2.4.0.1963_Binaries.zip, unzip it and run ILSpy.exe. There is no installer. If you open \Examples\4) DotNet_LoadAssembly\XPTable.dll through the File | Open... menu you'll see this information in the right pane window: // ...\Examples\4) DotNet_LoadAssembly\XPTable.dll // XPTable, Version=1.1.0.27823, Culture=neutral, PublicKeyToken=24950705800d2198 // Global type: <Module> // Architecture: AnyCPU (64-bit preferred) // Runtime: .NET 1.1 using System; using System.Reflection; [assembly: AssemblyVersion("1.1.0.27823")] [assembly: CLSCompliant(true)] [assembly: AssemblyCompany("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCopyright("Copyright © 2005, Mathew Hall. All rights reserved.")] [assembly: AssemblyDelaySign(false)] [assembly: AssemblyDescription("A fully customisable ListView style control based on Java's JTable")] [assembly: AssemblyKeyFile("..\\..\\XPTable.snk")] [assembly: AssemblyKeyName("")] [assembly: AssemblyProduct("XPTable")] [assembly: AssemblyTitle("XPTable")] [assembly: AssemblyTrademark("")] Note the comments in the top. This line: // Architecture: AnyCPU (64-bit preferred) means that the DLL-file can be used as both a 32 and a 64 bit .NET assembly DLL-file. Using C# and VB Code in AutoIt Using C# and VB Code in AutoIt through .NET Framework is an example that uses DotNet.au3 UDF in order to be able to execute compiled C# and VB code in AutoIt scripts. Zip-file The zip-file contains two folders: Examples\ and Includes\. The project depends on eight include files of which DotNet.au3 is the actual UDF. To make it easier to use the UDF, all include files are collected in one large file: DotNetAll.au3. To use DotNet.au3 UDF in your own project just include 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. DotNet.7z1 point -
Extended Message Box - New Version: 16 Feb 24
hudsonhock reacted to Melba23 for a topic
Are you annoyed by the limitations of the standard Windows message dialog created by MsgBox? Would you like to have coloured backgrounds and text? To choose the justification and font? Do you want to be able to place the message box other than in the centre of the screen? Centred on your GUI, for example, or at a particular location on screen? What about having user-defined text on as many buttons as you need? And user-defined icons? Or a visible countdown of the timeout? Finally, would you like to choose whether the message box has a button on your already too-crowded taskbar? If the answer to any of these questions is "YES" then the ExtMsgBox UDF is for you! [NEW VERSION] 16 Feb 24 Changed: Some additional functionality added to the "TimeOut" parameter of _ExtMsgBox: - A positive integer sets the EMB timeout as before. - A negative integer will double the size of the countdown timer if it is used. - A colon-delimited string (eg: "10:5") will set the normal EMB timeout (first integer) and will also initially disable the EMB buttons for the required period (second integer). New UDF and examples in the zip. Older version changes: ChangeLog.txt As always, I realise nearly all of the DLL calls in these UDFs could be made by using commands in other UDFs like WinAPI.au3 - but as with all my UDFs (which you can find in my sig below) I am trying to prevent the need for any other include files. The UDF and examples (plus StringSize) in zip format: ExtMsgBox.zip Courteous comments and constructive criticisms welcome - guess which I prefer! M231 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
-
Animated GIF without flickering
AndroidZero reacted to UEZ for a topic
Try something like this here: ;************FOR GATHER HTML SOURCE CODE********************** #include <IE.au3> #include <InetConstants.au3> ;************FOR GUI*********** #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <WinAPIFiles.au3> ;**********FOR BUTTON ********** #include <ButtonConstants.au3> #include <StaticConstants.au3> ;**********FOR STRINGS ********** #include <StringConstants.au3> #include <String.au3> ;**********FOR COMBOBOX ********** #include <StringConstants.au3> #include <EditConstants.au3> #include <GuiEdit.au3> #include <GuiComboBox.au3> ;**********FOR FONTS ********** #include <FontConstants.au3> ;**********FOR PROCESS ********** #include <Process.au3> #include <SendMessage.au3> #include <GDIPlus.au3> #include <WinAPIDiag.au3> Opt("GUIOnEventMode",1) Global Const $SC_DRAGMOVE = 0xF012 Global $hGUIAccountCreator Global $graphics_path = @ScriptDir ;& "\graphics" Global $fontSize_TextBody = 8.5, $fontName_TextBody = "", $fontWeight_TextBody = $FW_BOLD, $fontColor_TextBody = 0x5A2800 GUI_open_AccountCreator() Func GUI_open_AccountCreator() Global $hGUIAccountCreator = GUICreate("Tibia Account Creator - SubZero", 350, 400, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_Close_AccountCreator") GUICtrlCreatePic($graphics_path & "\WindowAccountCreator.gif", 0, 0, 350, 400) GUICtrlSetState(-1, $GUI_DISABLE) ;********* GUI CONTROLS (LABELS,INPUTS,COMBOBOXES) ********************************************************************** GUICtrlCreateLabel(" Create New Account", 25,47,103,14,$SS_CENTERIMAGE) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1,8,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetColor(-1,0xFFFFFF) GUICtrlCreateLabel("Account Name:",30,75,75,14) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1,8,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetColor(-1,0x5A2800) Global $inptBox_Acc = GUICtrlCreateInput("",130,75,150,20) GUICtrlCreateLabel("Email Adress:",30,100,70,14) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1,8,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetColor(-1,0x5A2800) Global $inptBox_Email = GUICtrlCreateInput("",130,100,150,20) GUICtrlCreateLabel("Password:",30,125,55,14) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1,8,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetColor(-1,0x5A2800) Global $inptBox_Passwd = GUICtrlCreateInput("",130,125,150,20,$ES_PASSWORD) GUICtrlSetData($inptBox_Passwd, "") GUICtrlCreateLabel("Character Name:",30,170,83,14) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1,8,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetColor(-1,0x5A2800) Global $inptBox_CharName = GUICtrlCreateInput("",130,170,150,20) GUICtrlCreateLabel("Sex:",30,195,23,14) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1,$fontSize_TextBody,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetFont(-1,8,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetColor(-1,$fontColor_TextBody) Global $comboBox_sex = GUICtrlCreateCombo("",130,195,150,20,$CBS_DROPDOWNLIST) ;LoadSexIntoComboBox() GUICtrlCreateLabel("World Location:",30,240,77) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1,$fontSize_TextBody,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetFont(-1,8,$fontWeight_TextBody,0,$fontName_TextBody,1) GUICtrlSetColor(-1,$fontColor_TextBody) Global $comboBox_world = GUICtrlCreateCombo("",130,240,150,20,BitOr($CBS_DROPDOWNLIST, $WS_VSCROLL)) ;LoadWorldsIntoComboBox() Global $label_status = GUICtrlCreateLabel("",20,360,200,30) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) ;********* GUI CONTROLS (LABELS,INPUTS,COMBOBOXES) ********************************************************************** ;********* CONTROL PICS ********************************************************************** Global $btn_randAccName = GUICtrlCreatePic("", 280, 75) GUICtrlSetTip($btn_randAccName, "Generate a random account name") GUICtrlSetCursor($btn_randAccName,0) ;GUICtrlSetOnEvent($btn_randAccName,"GenerateRandomAccName") GUICtrlSetOnEvent($btn_randAccName,"GUIChangeImage") Global $btn_x = GUICtrlCreatePic("", 315, 5, 40, 36) GUICtrlSetTip($btn_x, "Close") GUICtrlSetCursor($btn_x,0) GUICtrlSetOnEvent($btn_x,"GUI_Close_AccountCreator") Global $btn_donate = GUICtrlCreatePic("", 112, 313, 126, 47) GUICtrlSetTip($btn_donate, "Donate") GUICtrlSetCursor($btn_donate,0) ;GUICtrlSetOnEvent($btn_donate,"Donate") ;********* CONTROL PICS ********************************************************************** ;********* GDI+ DRAW ********************************************************************** _GDIPlus_Startup() Global $hImg = _GDIPlus_ImageLoadFromFile($graphics_path & "\X_Tic-Tac-Toe_Token.gif") Global $hHBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImg) _WinAPI_DeleteObject(GUICtrlSendMsg($btn_x, 0x0172, $IMAGE_BITMAP, $hHBMP)) _GDIPlus_ImageDispose($hImg) Global $hImg = _GDIPlus_ImageLoadFromFile($graphics_path & "\btn_donateCC_LG.gif") Global $hHBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImg) _WinAPI_DeleteObject(GUICtrlSendMsg($btn_donate, 0x0172, $IMAGE_BITMAP, $hHBMP)) _GDIPlus_ImageDispose($hImg) Global $aGIFs[6] For $i = 2 To 5 $hImg = _GDIPlus_ImageLoadFromFile($graphics_path & "\Die_Frame" & $i & ".gif") $aGIFs[$i - 1] = _GDIPlus_Convert2HBitmap($hImg, 0xD4C0A1, 32, 32) _GDIPlus_ImageDispose($hImg) Next $hImg = _GDIPlus_ImageLoadFromFile($graphics_path & "\Die_Static.gif") $aGIFs[0] = _GDIPlus_Convert2HBitmap($hImg, 0xD4C0A1, 32, 32) _WinAPI_DeleteObject(GUICtrlSendMsg($btn_randAccName, 0x0172, $IMAGE_BITMAP, $aGIFs[0])) _GDIPlus_ImageDispose($hImg) _GDIPlus_Shutdown() ;********* GDI+ DRAW ********************************************************************** _WinAPI_SetLayeredWindowAttributes($hGUIAccountCreator, 0x26f50b) GUISetIcon(@ScriptDir & "\TibiaInfo.ico") GUISetState(@SW_SHOW, $hGUIAccountCreator) WinSetOnTop($hGUIAccountCreator,"",1) GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN") EndFunc Func GUIChangeImage() For $i = 1 to 4 _WinAPI_DeleteObject(GUICtrlSendMsg($btn_randAccName, 0x0172, $IMAGE_BITMAP, $aGIFs[$i])) Sleep(200) Next _WinAPI_DeleteObject(GUICtrlSendMsg($btn_randAccName, 0x0172, $IMAGE_BITMAP, $aGIFs[0])) EndFunc Func GUI_Close_AccountCreator() For $i = 0 To 5 _WinAPI_DeleteObject($aGIFs[$i]) Next Exit EndFunc Func _WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam) _SendMessage($hGUIAccountCreator, $WM_SYSCOMMAND, $SC_DRAGMOVE, 0) EndFunc While 1 Sleep(100) WEnd Func _GDIPlus_Convert2HBitmap($hBitmap, $iBgColor, $iNewW = 0, $iNewH = 0) Local $iWidth, $iHeight If $iNewW Then $iWidth = $iNewW Else $iWidth = _GDIPlus_ImageGetWidth($hBitmap) EndIf If $iNewH Then $iHeight = $iNewH Else $iHeight = _GDIPlus_ImageGetHeight($hBitmap) EndIf Local $hBitmap_new = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight) ;$aResult[6] Local $hCtx_new = _GDIPlus_ImageGetGraphicsContext($hBitmap_new) _GDIPlus_GraphicsSetPixelOffsetMode($hCtx_new, $GDIP_PIXELOFFSETMODE_HIGHQUALITY) Local $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000 + $iBgColor) _GDIPlus_GraphicsFillRect($hCtx_new, 0, 0, $iWidth, $iHeight, $hBrush) _GDIPlus_GraphicsDrawImageRect($hCtx_new, $hBitmap, 0, 0, $iWidth, $iHeight) Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_new) _GDIPlus_BrushDispose($hBrush) _GDIPlus_BitmapDispose($hBitmap_new) _GDIPlus_GraphicsDispose($hCtx_new) Return $hHBITMAP EndFunc ;==>_GDIPlus_Convert2HBitmap1 point -
Check Checkbox by Name
13lack13lade reacted to InnI for a topic
#include "CUIAutomation2.au3" $Checked = _GetCheckBoxState(ControlGetHandle("Personal Options", "", "[NAME:chkShortPortfolios]")) If Not @error And Not $Checked Then ControlSend("Personal Options", "", "[NAME:chkShortPortfolios]", "{space}") Func _GetCheckBoxState($hControl) Local $oUIAutomation, $pElement, $oElement, $iState, $iErrorCode $oUIAutomation = ObjCreateInterface($sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtagIUIAutomation) If Not IsObj($oUIAutomation) Then Return SetError(1, 0, -1) $oUIAutomation.ElementFromHandle($hControl, $pElement) $oElement = ObjCreateInterface($pElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement) If Not IsObj($oElement) Then Return SetError(2, 0, -1) $iErrorCode = $oElement.GetCurrentPropertyValue($UIA_ToggleToggleStatePropertyId, $iState) If $iErrorCode Then Return SetError(3, 0, -1) Return $iState EndFunc1 point -
Beta version 0.9 released. This is a major upgrade, enabling HighMem allocations to be shared between multiple processes (after parsing their relative offset through any means of IPC). An example script (#20) with mutex negotiation will be included in the next release (4.1) of my matrix computing environment, coming soon(ish).1 point
-
As of firefox 55, mozrepl has stopped working. This means FF.au3 has stopped working and hence all our scripts based on it.. I have temporarily reverted and frozen firefox to ver 54 as I have a few work related scripts that I need to function properly. But this freeze can't last forever. Most of my work related stuff uses direct APIs into work systems and are fine. But I do have a couple that access data via firefox. (thank goodness for backups as the upgrade process to 55 messes with the firefox profile.) Then of course there is a lot of personal stuff using firefox as that is my preferred browser. I've looked but I don't see any discussion on whats happening with firefox switching to what they call webextentions as it pertains to autoit. If there is, then great. point me at it so I can read up on it. I've only found a couple post from months ago pointing out that changes are coming to firefox but nothing further. I guess those changes are now here. I've used FF.au3 for a few years. What is the current preferred method of accessing and controlling firefox? If there is an alternate method I should be learning so I can start in on it. If mozrepl and FF.au3 was still the common method then is anyone aware of planned updates? I don't think mozrepl has been touched in years and I'm sure I saw a post saying its no longer being maintained. Are we in a waiting game? Should I be learning some other method that works and will continue to work? Is there a way to access the new webextention api methods or is that only available to an actual extension? Cal.1 point