Leaderboard
Popular Content
Showing content with the highest reputation on 10/29/2021 in all areas
-
KPScript UDF (KeePass automation)
TheDcoder reacted to seadoggie01 for a topic
This UDF automates KeePass databases through the use of KPScript, a plugin for KeePass that is developed by the original author. This is something I've wanted for a long time. I really like KeePass and I really like using AutoIt, but I feel uncomfortable typing clear text passwords into my scripts. I can only get away with using Send("^!a") to try to get KeePass to input my passwords for me for so long. To download the UDF, head over to GitHub for now (this is easier for me to manage). When I get a release version, I'll update this post with more info and a link to download from the forums. Be sure to read the Notes section, and let me know of any issues, features, or praise you might have!1 point -
The .NET IntPtr type is useful for copying data in the form of memory blocks between managed .NET code and unmanaged AutoIt code. An advantage of using this technique is that the data copying isn't subject to internal AutoIt COM conversions. This means that even copying large memory blocks can be done very fast. A disadvantage is that such memory blocks can only be handled through DllStructs in AutoIt, unless the memory blocks can be used directly eg. if they represent image data. Another technique for passing data between AutoIt and C#/VB.NET is demonstrated in Using C# and VB Code. With this technique, variables and arrays are exchanged through comparable COM data types. Eg. passing an AutoIt array to .NET as a safearray of variants. On the AutoIt side the safearray of variants is created through internal AutoIt COM conversions. On the .NET side data is received as an array of objects. Although the COM conversions are performed by internal AutoIt functions as compiled C/C++ code, the conversions take some time for large arrays. Since AutoIt arrays are limited to 2^24 = 16,777,216 elements, this is the maximum amount of data that can be passed at one time. DotNetAll.au3 UDFCommon to the two techniques is that they are both based on DotNetAll.au3 UDF (contained in the 7z-file below). The DotNetAll.au3 UDF is by far the easiest way to execute compiled and multi-threaded code in AutoIt through C# or VB.NET code, thereby managing bottlenecks in the AutoIt code. With this new IntPtr data copying technique, it's possible to handle more bottlenecks than can be handled with the existing COM data passing technique. The benefits of the DotNetAll.au3 UDF are: The .NET source code can be easily written in SciTE without the need for a specific development tool The .NET code is compiled and executed directly in your AutoIt script, where you apply the code If the AutoIt script is run in SciTE with F5, .NET error messages appear in the console The .NET code can be easily distributed in the form of source files (text files) You avoid the registration/unregistration tyranny of .NET assembly Dll files Although DotNetAll.au3 UDF contains a lot of code, it's a complete UDF in the way that you can concentrate on the main functions. There's no need to go through all the details of the code. There are two main functions in the UDF. A function for loading C#/VB.NET code and a function for creating an object based on the C#/VB.NET class. In AutoIt, the functions are used as follows: Local $oNetCode = DotNet_LoadVBcode( FileRead( "Example01.vb" ), "System.dll" ) ; Load VB.NET code Local $oNetCode = DotNet_LoadCScode( FileRead( "Example02.cs" ), "System.dll" ) ; Load C# code Local $oTestClass = DotNet_CreateObject( $oNetCode, "TestClass" ) ; Create object Then just call the object methods and get/set the object properties. This is demonstrated in the examples below. ExamplesThe examples can be found in the Examples folder. All examples use the DotNetAll.au3 UDF, which is located in the Includes folder. It's the only file in Includes. Only the Introductory examples demonstrates C# code. Since VB.NET code is most easily accessible with an AutoIt background, the rest of the examples are shown only as VB.NET code. Note that in all examples, all memory allocation and all data copying is performed exclusively in the .NET code. Run the examples with F5 in SciTE. Memory Access Violation error The Introductory examples and Performance measurements all caused a Memory Access Violation error and a consequent crash in the first version of the examples when executed on Windows 10 as 64 bit code. This is because the IntPtr data type isn't handled correctly in AutoIt on Windows 10 as 64 bit code. This applies to all AutoIt versions including the current beta. The usual workaround is to return the IntPtr as a string. This error occurs when IntPtr is a void memory pointer. However, the error does not occur if IntPtr refers to a memory block that represents a valid handle or HWnd memory block. This is because a handle and HWnd pointer by Microsoft definition is a 4 byte pointer in both 32 and 64 bit code. In 64 bit code, the 4 most significant bytes are therefore all zeros. Thus, there are no errors in the Image manipulation examples. The function definition and return lines therefore looks like this in the published version in the 7z-file of the Introductory examples and Performance measurements (VB.NET code): Public Function Test() As String ... Return pnt.ToString() And look like this in Image manipulation examples (VB.NET code): Public Function Test() As IntPtr ... Return hBitmap Introductory examplesWith the IntPtr technique, part of the code is based on the .NET Marshal Class. The introductory examples in \1) Examples\ demonstrate how to apply this class. Example01.au3 and Example01.vb show how to copy a memory block of 16 bytes from VB.NET to AutoIt: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include "..\..\Includes\DotNetAll.au3" Example() Func Example() ; Load .NET code, create object, execute method Local $oNetCode = DotNet_LoadVBcode( FileRead( "Example01.vb" ), "System.dll" ) Local $oTestClass = DotNet_CreateObject( $oNetCode, "TestClass" ) Local $pPtr = $oTestClass.Test() ; View data as a DllStruct of Bytes Local $tBytes = DllStructCreate( "byte[16]", $pPtr ) ; Display data For $i = 1 To 16 ConsoleWrite( StringFormat( "$tBytes[%2s]", $i ) & StringFormat( " = %3s", DllStructGetData( $tBytes, 1, $i ) ) & @CRLF ) Next EndFunc Imports System Imports System.Runtime.InteropServices Class TestClass Public Function Test() As String 'Create and fill aArray with values 97 - 112 Dim aArray(15) As Byte For i As Integer = 0 To 15 aArray(i) = i + 97 Next 'Allocate memory in unmanaged AutoIt code Dim size As Integer = Marshal.SizeOf( aArray(0) ) * aArray.Length Dim pnt As IntPtr = Marshal.AllocHGlobal( size ) 'Copy from VB.NET to AutoIt 'Copy data to unmanaged memory Marshal.Copy( aArray, 0, pnt, aArray.Length ) 'Return memory pointer to AutoIt Return pnt.ToString() End Function End Class Example02.cs is a C# version of the same code: using System; using System.Runtime.InteropServices; class TestClass { public String Test() { // Create and fill aArray with values 97 - 112 byte[] aArray = new byte[16]; for( int i = 0; i < 16; i++ ) { aArray[i] = (byte)(i+97); } // (byte) => cast to byte // Allocate memory in unmanaged AutoIt code int size = Marshal.SizeOf( aArray[0] ) * aArray.Length; IntPtr pnt = Marshal.AllocHGlobal( size ); // Copy from C# to AutoIt // Copy data to unmanaged memory Marshal.Copy( aArray, 0, pnt, aArray.Length ); // Return memory pointer to AutoIt return pnt.ToString(); } } The code in Example02.au3 is the same as the code in Example01.au3. Example03.au3, Example03.vb and Example04.cs show how to copy a memory block of 16 bytes from AutoIt to VB.NET/C#. Performance measurementsExample01.au3 in \2) Runtimes\ calls the same Example() function 4 times: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include "..\..\Includes\DotNetAll.au3" Example( 1000000, True ) ; 1,000,000 Example( 1000000 ) ; 1,000,000 Example( 16777216 ) ; 16,777,216 = 2^24 Example( 100000000 ) ; 100,000,000 Func Example( $iInts, $bDisplay = False ) ; Load .NET code, create object Local $oNetCode = DotNet_LoadVBcode( FileRead( "Example01.vb" ), "System.dll" ) Local $oTestClass = DotNet_CreateObject( $oNetCode, "TestClass" ) ; Pass number of integers to VB.NET code $oTestClass.Test0( $iInts ) ; Create and fill VB.NET integer aArray with $iInts elements ; Allocate memory through managed VB.NET code Local $pPtr = $oTestClass.Test1() ; Copy $iInts integers from .NET aArray to AutoIt Local $hTimer = TimerInit() $oTestClass.Test2() ConsoleWrite( @CRLF & "Time to copy " & StringRegExpReplace( $iInts, "(\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))", "\1" & "," ) & _ " integers from .NET aArray to AutoIt" & ( $bDisplay ? " = " : " = " ) & TimerDiff( $hTimer ) & @CRLF ) $hTimer = 0 ; View aArray data as a DllStruct of Bytes Local $tUints = DllStructCreate( "uint[" & $iInts & "]", $pPtr ) ; Display data If $bDisplay Then For $i = $iInts/2 To $iInts/2+16 ConsoleWrite( "$tUints[" & $i & "]" & " = " & DllStructGetData( $tUints, 1, $i+1 ) & @CRLF ) Next ConsoleWrite( @CRLF ) EndIf ; Copy $iInts integers from AutoIt to .NET aArray2 $hTimer = TimerInit() $oTestClass.Test3() ConsoleWrite( "Time to copy " & StringRegExpReplace( $iInts, "(\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))", "\1" & "," ) & _ " integers from AutoIt to .NET aArray2 = " & TimerDiff( $hTimer ) & @CRLF ) $hTimer = 0 ; Display aArray2 data If $bDisplay Then $oTestClass.Test4() If $iInts <= 16777216 And Not $bDisplay Then Local $aArray2 ; Pass $iInts integers from .NET aArray2 to AutoIt $aArray2 ; .NET aArray2 is returned from a method directly into AutoIt $aArray2 ; In this way aArray2 is passed as a safearray of integers through default marshalling ; Internal AutoIt COM conversions of the safearray converts it to a native AutoIt array $hTimer = TimerInit() $aArray2 = $oTestClass.Test5() ConsoleWrite( @CRLF & "Time to pass " & StringRegExpReplace( $iInts, "(\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))", "\1" & "," ) & _ " integers from .NET aArray to AutoIt $aArray2 = " & TimerDiff( $hTimer ) & @CRLF ) $hTimer = 0 ; Pass $iInts integers from AutoIt $aArray2 to .NET aArray3 ; AutoIt $aArray2 is passed as a function parameter directly into .NET aArray3 ; Internal AutoIt COM conversions pass $aArray2 as a safearray of variants with variant type integer ; The safearray of variants is passed to .NET through default marshalling as an array of objects with object type integer $hTimer = TimerInit() $oTestClass.Test6( $aArray2 ) ConsoleWrite( "Time to pass " & StringRegExpReplace( $iInts, "(\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))", "\1" & "," ) & _ " variants from AutoIt $aArray2 to .NET aArray3 = " & TimerDiff( $hTimer ) & @CRLF ) $hTimer = 0 EndIf ConsoleWrite( @CRLF ) EndFunc Imports System Imports System.Runtime.InteropServices Class TestClass 'Globals in class Dim pnt As IntPtr Dim iInts As Integer Dim aArray() As Integer Dim aArray2() As Integer Public Sub Test0( iElements As Integer ) 'Get number of integers iInts = iElements ReDim aArray( iInts-1 ) ReDim aArray2( iInts-1 ) End Sub Public Function Test1() As String 'Create and fill integer aArray with iInts elements For i As Integer = 0 To iInts-1 aArray(i) = i Next 'Allocate memory in unmanaged AutoIt code Dim size As Integer = Marshal.SizeOf( aArray(0) ) * aArray.Length pnt = Marshal.AllocHGlobal( size ) 'Return memory pointer to AutoIt Return pnt.ToString() End Function Public Sub Test2() 'Copy iInts integers from .NET aArray to AutoIt Marshal.Copy( aArray, 0, pnt, aArray.Length ) End Sub Public Sub Test3() 'Copy iInts integers from AutoIt to .NET aArray2 Marshal.Copy( pnt, aArray2, 0, iInts ) End Sub Public Sub Test4() 'Display aArray2 data For i As Integer = iInts/2 To iInts/2+15 Console.WriteLine( "aArray2({0}) = {1}", i, aArray2(i) ) Next End Sub Public Function Test5() As Integer() 'Pass iInts integers from .NET aArray2 to AutoIt Return aArray2 End Function Public Sub Test6( aArray3 As Object() ) 'Pass iInts variants from AutoIt to .NET aArray3 Dim iLength As Integer = aArray3.Length 'Console.WriteLine( "iLength = {0}", iLength ) End Sub End Class In the first example, time measurements are made and a few data are printed in the console. In the other 3 examples, only time measurements are performed. The text box below is console output for these 3 examples. The "copy" lines are time measurements for the new IntPtr data copying technique. The "pass" lines are time measurements for the old COM data passing technique. Time to copy 1,000,000 integers from .NET aArray to AutoIt = 1.72992070180921 Time to copy 1,000,000 integers from AutoIt to .NET aArray2 = 1.72077794345564 Time to pass 1,000,000 integers from .NET aArray to AutoIt $aArray2 = 45.4910409279733 Time to pass 1,000,000 variants from AutoIt $aArray2 to .NET aArray3 = 218.360099451047 Time to copy 16,777,216 integers from .NET aArray to AutoIt = 19.8287034959137 Time to copy 16,777,216 integers from AutoIt to .NET aArray2 = 23.0162015219091 Time to pass 16,777,216 integers from .NET aArray to AutoIt $aArray2 = 743.615722663014 Time to pass 16,777,216 variants from AutoIt $aArray2 to .NET aArray3 = 4165.03925567973 Time to copy 100,000,000 integers from .NET aArray to AutoIt = 118.826768001676 Time to copy 100,000,000 integers from AutoIt to .NET aArray2 = 115.565850855568 The results clearly show that the new copying technique is much faster than the old passing technique. In particular, passing arrays from AutoIt to .NET is slow with the old technique. With the new technique, very large amounts of data can be copied. The reason for the slow passing of AutoIt arrays to .NET is that AutoIt arrays can only be passed as safearrays of variants. And passing variants is time consuming. Not at least due to internal AutoIt COM conversions which perform a by value copy of all AutoIt array elements into variant structures in the safearray. Image manipulationExample01.au3 and Example01.vb in \3) Images\ shows how to load an image in VB.NET and display the image in AutoIt: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include "..\..\Includes\DotNetAll.au3" Example() Func Example() ; Load .NET code, create object, execute method Local $oNetCode = DotNet_LoadVBcode( FileRead( "Example01.vb" ), "System.dll | System.Drawing.dll" ) Local $oTestClass = DotNet_CreateObject( $oNetCode, "TestClass" ) Local $pBitmap = $oTestClass.Test() ; Create GUI Local $hGui = GUICreate( "GDI+ Through .NET", 240, 164 ) GUISetState( @SW_SHOW ) ; Initialize GDI+ _GDIPlus_Startup() ; Draw bitmap to GUI Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP( $pBitmap ) Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND( $hGui ) _GDIPlus_GraphicsDrawImage( $hGraphic, $hBitmap, 0, 0 ) ; Clean up resources _GDIPlus_GraphicsDispose( $hGraphic ) _GDIPlus_BitmapDispose( $hBitmap ) _WinAPI_DeleteObject( $pBitmap ) ; Shut down GDI+ _GDIPlus_Shutdown() ; Loop Do Until GUIGetMsg() = $GUI_EVENT_CLOSE EndFunc Imports System Imports System.Drawing Class TestClass Public Function Test() As IntPtr 'Create a bitmap Dim bmp As New Bitmap( "Test.bmp" ) 'Create a GDI bitmap Dim hBitmap As IntPtr = bmp.GetHbitmap() 'Return GDI bitmap Return hBitmap End Function End Class Note that at the bottom of Example01.vb, the GDI bitmap pointer (hBitmap) is passed directly from VB.NET to AutoIt without a copy of the corresponding memory block. This is because the memory layout for a GDI bitmap memory block is the same in .NET and AutoIt. The same GDI bitmap memory block can without any further be used in both .NET and AutoIt. Without data copying, the code is very fast. Example02.au3 (same as Example01.au3) and Example02.vb is an example of real image manipulation. However, simple image manipulation. It's the same image as above, which is a 24 bpp (bits per pixel) image. 8 bits or 1 byte is used per RGB color. In the example, all the red bytes are set to the value 255 so that the whole image gets a red expression. Imports System Imports System.Drawing Imports System.Drawing.Imaging Imports System.Runtime.InteropServices Class TestClass Public Function Test() As IntPtr 'Create bitmap Dim bmp As New Bitmap( "Test.bmp" ) 'Lock the bits in the bitmap Dim rect As New Rectangle( 0, 0, bmp.Width, bmp.Height ) Dim bmpData As BitmapData = bmp.LockBits( rect, ImageLockMode.ReadWrite, bmp.PixelFormat ) 'Get the address of the first line Dim ptr As IntPtr = bmpData.Scan0 'Declare an array to hold the bytes of the bitmap 'This code is specific to a bitmap with 24 bits per pixel (bpp) Dim iBytes As Integer = Math.Abs( bmpData.Stride ) * bmp.Height Dim aRGBValues(iBytes-1) As Byte 'Copy the RGB values into the array Marshal.Copy( ptr, aRGBValues, 0, iBytes ) 'Set every third value to 255, a 24bpp image will look red For i As Integer = 2 To aRGBValues.Length - 1 Step 3 aRGBValues(i) = 255 Next 'Copy the RGB values back to the bitmap Marshal.Copy( aRGBValues, 0, ptr, iBytes ) 'Unlock the bits bmp.UnlockBits( bmpData ) 'Create GDI bitmap Dim hBitmap As IntPtr = bmp.GetHbitmap() 'Return GDI bitmap Return hBitmap End Function End Class Posts below Post 2 and the following posts is a discussion of the possibilities of executing PowerShell commands and scripts directly in AutoIt, and returning PowerShell output back to AutoIt. This is possible through C# code that acts as a host to execute PowerShell commands and scripts. C# Pointers demonstrates the use of pointers to performance optimize C# code. Use of structures to transfer data between AutoIt and .NET. Struct arrays in .NET code 7z-fileThe 7z-file contains source code for UDFs and examples. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Comments are welcome. Let me know if there are any issues. DotNetIntPtr.7z1 point
-
Look at these functions in helpfile: WinGetState() ControlGetFocus()1 point
-
I assume that your expectation of the code line with the ObjCreateInterface() function is that it gives you a new reference to the $oDict_A object. Ie. that $oDict_A and $oDict_B are two different references to the same object. But that's not the case. $oDict_B is a new object apparently created in the same memory block as $oDict_A. That's why you get Memory Access Violation errors. You also assume that your code works. But it doesn't. This is because you have only tested the code that works. You haven't tested the code that doesn't work. You create two references $oDict_A and $oDict_B to the same object this way. Because they are two references to the same object, this code works. Example() Func Example() Local $oDict_A = ObjCreate( "Scripting.Dictionary" ) ; Object reference counter = 1 $oDict_A( "Test" ) = 123 ConsoleWrite( "$oDict_A( ""Test"" ) = " & $oDict_A( "Test" ) & @CRLF ) $oDict_B = $oDict_A ; $oDict_A and $oDict_B references the same object ; Object reference counter = 2 $oDict_A = 0 ; Object reference counter = 1 ConsoleWrite( "$oDict_B( ""Test"" ) = " & $oDict_B( "Test" ) & @CRLF ) EndFunc If you test the same code (deletion of $oDict_A) with your $oDict_A and $oDict_B objects you'll see that the code doesn't work after deletion of $oDict_A. #include <WinAPICom.au3> __Example1() Func __Example1() Local $String_A = "Apple" _WinAPI_CoInitialize( $COINIT_APARTMENTTHREADED ) Local $oDict_A = ObjCreate( "Scripting.Dictionary" ) If IsObj($oDict_A) Then $oDict_A.add("$String_A", $String_A) ConsoleWrite("----->" & @CRLF) ConsoleWrite("[$oDict_A] [$String_A] => " & $oDict_A.Item("$String_A") & @CRLF) Local $pObject = Ptr( $oDict_A ) Local $oDict_B = ObjCreateInterface($pObject, "{42C642C1-97E1-11CF-978F-00A02463E06F}", Default, False) If @error Then ConsoleWrite("ObjCreateInterface failed.... Error code: " & Hex(@error, 8) & @CRLF) $oDict_A = 0 Exit Endif $oDict_A = 0 ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ConsoleWrite("----->" & @CRLF) ConsoleWrite("$oDict_A has been deleted" & @CRLF) Local $String_B = "Orange" $oDict_B.add("$String_B", $String_B) ConsoleWrite("----->" & @CRLF) ConsoleWrite("[$oDict_B] [$String_B] => " & $oDict_B.Item("$String_B") & @CRLF) ConsoleWrite("[$oDict_B] [$String_A] => " & $oDict_B.Item("$String_A") & @CRLF) ConsoleWrite("----->" & @CRLF) _WinAPI_CoUninitialize() $oDict_B = 0 Endif EndFunc The fact that $oDict_B doesn't work when $oDict_A is deleted clearly indicates that $oDict_A and $oDict_B aren't references to the same object. If they were, the code would have worked. $oDict_A and $oDict_B are two different objects. That parts of the code works as in your example along with all the Memory Access Violation errors indicates that the two objects have overlapping memory blocks. If you just want to create a new reference to an existing object simply use $oDict_B = $oDict_A.1 point
-
_FileWriteToLine("testy.txt", $i+1, "three is 3", True)1 point
-
simple bot does not working
Musashi reacted to Earthshine for a topic
he marked his question as the solution--it doesn't make any sense. oh well.1 point -
Ooops, thought my script was in my signature I added it to GitHub a while ago: https://github.com/seadoggie01/KPScript and a topic on our forums: I've made some changes recently, but I need to test before I upload. There aren't any examples, but it's not too hard to use... (Note: no error checking here, add your own) Local Const $sKPScript = @AppDataDir & "\KeePass\KPScript.exe" Local Const $sKeePass = @UserProfileDir & "\Documents\KeePass.kdbx" ; Using Windows based Authentication Local $aUnlockKey = _KPScript_UnlockKey(Default, Default, Default, True) ; Like a search expression for _KPScript_EntryStringGet Local $aIdentification = _KPScript_EntryIdentify("Title", "<Value of Title>") ; Now actually unlock the database and perform the search Local $sUserName = _KPScript_EntryStringGet($sKPScript, $sKeePass, $aUnlockKey, "UserName", $aIdentification) Local $sPassword = _KPScript_EntryStringGet($sKPScript, $sKeePass, $aUnlockKey, "Password", $aIdentification)1 point
-
too many image searches?
JockoDundee reacted to Musashi for a topic
You are right about that. I mainly wanted to point out to the OP, that his loop would run infinitely. He should be able to do the fine-tuning himself . Do [...] Until SiCounter = 500 If $bFound Then ToolTip(".... picture search") ... or the traditional statement from ancient computer times : FUBAR -> "He" Fucked Up Beyond All Repair1 point -
too many image searches?
Musashi reacted to JockoDundee for a topic
Right, but in both cases “he takes action”, assuming that the action is the ToolTip statement. Some people call a ship “she”, but these days it might get flagged as misogynistic. Calling a script “he” is a refreshing change, although some of the natural constructs might be awkward: He crashed. He bombed. I executed him.1 point -
Windows Environment Variables
Earthshine reacted to Subz for a topic
Don't believe you would get the SET results from CMD in the same session that the variable is added/updated. If you run your batch file manually afterwards it will show the correct results though. Normally I use the following to set and check environment variables. ;~ #RequireAdmin ;~ Required when writing to System Environment Variable ; #VARIABLES# =================================================================================================================== Global $MAX_VALUE_NAME = 1024 Global $HWND_BROADCAST = 0xffff Global $WM_SETTINGCHANGE = 0x001A Global $SMTO_ABORTIFHUNG = 0x0002 Global $SMTO_NORMAL = 0x0000 Global $MSG_TIMEOUT = 5000 ;~ ============================== Begin Example =============================== _EnvVarSet("MENU_HOME", "C:\Windows\Temp", 3) ConsoleWrite(_EnvVarGet("MENU_HOME") & @CRLF) ;~ =============================== End Example ================================ ; #FUNCTION# ==================================================================================================================== ; Name ..........: _EnvVarGet ; Description ...: Get Environment Variables ; Syntax ........: _EnvVarGet($_sEnvVarGet[, $_iEnvVarType = 3[, $_bExpVarValue = False]]) ; Parameters ....: $_sEnvVarGet - Environment variable name ; : $_iEnvVarType - [optional] Environment variable type. Default is 3. ; : - 0 - Returns Enviroment variable from all profile types ; : - 1 - Process Enviornment Variable ; : - 2 - System Enviornment Variable ; : - 3 - User Enviornment Variable ; : - 4 - Volatile Enviornment Variable ; : $_bExpVarValue - [optional] Expand Environment Variables within result. Default is False. ; Return values .: ; : Flag: $_iEnvVarType ; : - 0 - Returns Enviroment variable from all profile types as an array ; : - 1 - Process Enviornment Variable as a string ; : - 2 - System Enviornment Variable as a string ; : - 3 - User Enviornment Variable as a string ; : - 4 - Volatile Enviornment Variable as a string ; Author ........: Subz ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _EnvVarGet($_sEnvVarGet, $_iEnvVarType = 3, $_bExpVarValue = False) Local $iExpandEnvStrings = Opt("ExpandEnvStrings") Local $sEnvVarValue, $aEnvVarValue[5] = [4] Local $oEnvVarType, $aEnvVarType[5] = [4, "PROCESS", "SYSTEM", "USER", "VOLATILE"] Local $oWshShell = ObjCreate("WScript.Shell") Switch $_iEnvVarType Case 0 If $_bExpVarValue == True Then Opt("ExpandEnvStrings", 1) For $i = 1 To $aEnvVarType[0] $oEnvVarType = $oWshShell.Environment($aEnvVarType[$i]) $aEnvVarValue[$i] = $oEnvVarType($_sEnvVarGet) Next Opt("ExpandEnvStrings", $iExpandEnvStrings) Return $aEnvVarValue Case 1 To 4 If $_bExpVarValue == True Then Opt("ExpandEnvStrings", 1) $oEnvVarType = $oWshShell.Environment($aEnvVarType[$_iEnvVarType]) $sEnvVarValue = $oEnvVarType($_sEnvVarGet) Opt("ExpandEnvStrings", $iExpandEnvStrings) Return $sEnvVarValue Case Else Return SetError(1, 0, "") EndSwitch EndFunc ; #FUNCTION# ==================================================================================================================== ; Name ..........: _EnvVarSet ; Description ...: Set Environment Variables ; Syntax ........: _EnvVarSet($_sEnvVarName, $_sEnvVarValue, [, $_iEnvVarType = 3]) ; Parameters ....: $_sEnvVarName - Environment variable name. ; : $_iEnvVarValue - Environment variable value. ; : $_iEnvVarType - [optional] Environment variable type. Default is 3. ; : - 0 - Set Enviroment variable for all profile types ; : - 1 - Set Process Enviornment Variable ; : - 2 - Set System Enviornment Variable ; : - 3 - Set User Enviornment Variable ; : - 4 - Set Volatile Enviornment Variable ; Return values .: 0 - Success ; : 1 - Failed ; Author ........: Subz ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _EnvVarSet($_sEnvVarName, $_sEnvVarValue, $_iEnvVarType = 3) Local $oEnvVarType, $aEnvVarType[5] = [4, "PROCESS", "SYSTEM", "USER", "VOLATILE"] Local $oWshShell = ObjCreate("WScript.Shell") Switch $_iEnvVarType Case 0 For $i = 1 To $aEnvVarType[0] $oEnvVarType = $oWshShell.Environment($aEnvVarType[$i]) $oEnvVarType($_sEnvVarName) = $_sEnvVarValue Next Case 1 To 4 $oEnvVarType = $oWshShell.Environment($aEnvVarType[$_iEnvVarType]) $oEnvVarType($_sEnvVarName) = $_sEnvVarValue Case Else Return SetError(1) EndSwitch _EnvVarRefresh() If @error Then Return SetError(1) SetError(0) EndFunc ; #FUNCTION# ==================================================================================================================== ; Name ..........: _EnvVarDelete ; Description ...: Delete Environment Variables ; Syntax ........: _EnvVarDelete($_sEnvVarName, [$_iEnvVarType = 3]) ; Parameters ....: $_sEnvVarName - Environment variable name to delete ; : $_iEnvVarType - [optional] Environment variable type. Default is 3. ; : - 0 - Returns Enviroment variable from all profile types ; : - 1 - Process Enviornment Variable ; : - 2 - System Enviornment Variable ; : - 3 - User Enviornment Variable ; : - 4 - Volatile Enviornment Variable ; Return values .: 0 - Success ; : 1 - Failed ; Author ........: Subz ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _EnvVarDelete($_sEnvVarName, $_iEnvVarType = 3) Local $oEnvVarType, $aEnvVarType[5] = [4, "PROCESS", "SYSTEM", "USER", "VOLATILE"] Local $oWshShell = ObjCreate("WScript.Shell") Switch $_iEnvVarType Case 0 For $i = 1 To $aEnvVarType[0] $oEnvVarType = $oWshShell.Environment($aEnvVarType[$i]) $oEnvVarType.Remove($_sEnvVarName) Next Case 1 To 4 $oEnvVarType = $oWshShell.Environment($aEnvVarType[$_iEnvVarType]) $oEnvVarType.Remove($_sEnvVarName) Case Else Return SetError(1, 0, "") EndSwitch _EnvVarRefresh() If @error Then Return SetError(1) SetError(0) EndFunc Func _EnvVarRefresh() ; http://msdn.microsoft.com/en-us/library/ms644952%28VS.85%29.aspx $iRet2 = DllCall("user32.dll", "lresult", "SendMessageTimeoutW", _ "hwnd", $HWND_BROADCAST, _ "dword", $WM_SETTINGCHANGE, _ "ptr", 0, _ "wstr", "Environment", _ "dword", $SMTO_ABORTIFHUNG, _ "dword", $MSG_TIMEOUT, _ "dword_ptr*", 0) If $iRet2[0] = 0 Then Return SetError(1) EndFunc1 point -
Writing some VBA-Code to an excel file
Earthshine reacted to junkew for a topic
no, xlsx normally does not have macro's you should switch to xlsm no, normally security settings will not allow to do this yes if above is allowed you can alter your workbook with the vbide object model https://bettersolutions.com/vba/visual-basic-editor/extensibility-object-model.htm no, in general I would do this directly from excel vba editor1 point -
For the examples above, you must use ROT objects. This is a server/client implementation of your FakeObj. Server.au3: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include "IRunningObjectTable.au3" Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc") Example() Func Example() Local $tFakeObj, $oFakeObj $oFakeObj = _ObjectFromTag("__MyInterface_", "Message hresult(bstr)", $tFakeObj) $oFakeObj.Message("Test message from Server .....") ; Create a default ROT-object (Dictionary object) Local $sDataTransferObject, $oDataTransferObject $oDataTransferObject = ROT_CreateDefaultObject( $sDataTransferObject ) ; Create Dictionary object Local $oDict = ObjCreate( "Scripting.Dictionary" ) $oDict.Item( "$oFakeObj" ) = $oFakeObj ; Add Dictionary object to ROT-object $oDataTransferObject.Add( "$oDict", $oDict ) ; Start the client script in a new process RunWait( @AutoItExe & " /AutoIt3ExecuteScript Client.au3" & " " & $sDataTransferObject ) EndFunc Func __MyInterface_QueryInterface($pSelf, $pRIID, $pObj) Local $tStruct = DllStructCreate("ptr", $pObj) DllStructSetData($tStruct, 1, $pSelf) Return 0 ; $S_OK #forceref $pRIID EndFunc Func __MyInterface_AddRef($pSelf) Return 1 #forceref $pSelf EndFunc Func __MyInterface_Release($pSelf) Return 1 #forceref $pSelf EndFunc Func __MyInterface_Message($pSelf, $pString) Local $o_Data = DllStructGetData(DllStructCreate("wchar[" & _ DllStructGetData(DllStructCreate("dword", $pString - 4), 1) / 2 & "]", $pString), 1) MsgBox(0, 'FakeObj', $o_Data) Return 0 ; $S_OK #forceref $pSelf EndFunc ; #FUNCTION# ============================================================================= ; Name...........: _ObjectFromTag ; ======================================================================================== Func _ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface, $fPrint = False, $bIsUnknown = Default, $sIID = "{00000000-0000-0000-C000-000000000046}") ; last param is IID_IUnknown by default If $bIsUnknown = Default Then $bIsUnknown = True Local $sInterface = $tagInterface ; copy interface description Local $tagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _ "AddRef dword();" & _ "Release dword();" ; Adding IUnknown methods If $bIsUnknown Then $tagInterface = $tagIUnknown & $tagInterface ; Below line is really simple even though it looks super complex. It's just written weird to fit in one line, not to steal your attention Local $aMethods = StringSplit(StringReplace(StringReplace(StringReplace(StringReplace(StringTrimRight(StringReplace(StringRegExpReplace(StringRegExpReplace($tagInterface, "\w+\*", "ptr"), "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1), "object", "idispatch"), "hresult", "long"), "bstr", "ptr"), "variant", "ptr"), @LF, 3) Local $iUbound = UBound($aMethods) Local $sMethod, $aSplit, $sNamePart, $aTagPart, $sTagPart, $sRet, $sParams, $hCallback ; Allocation $tInterface = DllStructCreate("int RefCount;int Size;ptr Object;ptr Methods[" & $iUbound & "];int_ptr Callbacks[" & $iUbound & "];ulong_ptr Slots[16]") ; 16 pointer sized elements more to create space for possible private props If @error Then Return SetError(1, 0, 0) For $i = 0 To $iUbound - 1 $aSplit = StringSplit($aMethods[$i], "|", 2) If UBound($aSplit) <> 2 Then ReDim $aSplit[2] $sNamePart = $aSplit[0] $sTagPart = $aSplit[1] $sMethod = $sFunctionPrefix & $sNamePart If $fPrint Then Local $iPar = StringInStr($sTagPart, ";", 2), $t If $iPar Then $t = "Ret: " & StringLeft($sTagPart, $iPar - 1) & " " & _ "Par: " & StringRight($sTagPart, StringLen($sTagPart) - $iPar) Else $t = "Ret: " & $sTagPart EndIf Local $s = "Func " & $sMethod & _ "( $pSelf ) ; " & $t & @CRLF & _ "EndFunc" & @CRLF ConsoleWrite($s) EndIf $aTagPart = StringSplit($sTagPart, ";", 2) $sRet = $aTagPart[0] $sParams = StringReplace($sTagPart, $sRet, "", 1) $sParams = "ptr" & $sParams $hCallback = DllCallbackRegister($sMethod, $sRet, $sParams) If @error Then ConsoleWrite('! ' & @error & ' ' & $sMethod & @CRLF & @CRLF) EndIf DllStructSetData($tInterface, "Methods", DllCallbackGetPtr($hCallback), $i + 1) ; save callback pointer DllStructSetData($tInterface, "Callbacks", $hCallback, $i + 1) ; save callback handle Next DllStructSetData($tInterface, "RefCount", 1) ; initial ref count is 1 DllStructSetData($tInterface, "Size", $iUbound) ; number of interface methods DllStructSetData($tInterface, "Object", DllStructGetPtr($tInterface, "Methods")) ; Interface method pointers Return ObjCreateInterface(DllStructGetPtr($tInterface, "Object"), $sIID, $sInterface, $bIsUnknown) ; pointer that's wrapped into object EndFunc ;==>ObjectFromTag Func _ErrFunc() ConsoleWrite("! COM Error ! Number: 0x" & Hex($oError.number, 8) & " ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF) Return EndFunc ;==>_ErrFunc Client.au3: #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) Example() Func Example() ; Get default ROT-object (Dictionary object) Local $oDataTransferObject = ObjGet( $CmdLine[1] ) ; Get Dictionary object from ROT-object Local $oDict = $oDataTransferObject.Item( "$oDict" ) Local $oFakeObj = $oDict.Item( "$oFakeObj" ) $oFakeObj.Message("Test message from Client .....") EndFunc Run Server.au3. Come on. This is f ... (freezing) cool code. That was fun. All code in the 7z-file. FakeObj.7z You can try the other two examples yourself.1 point
-
UPDATE: With the addition of the ObjCreateInterface function and enhanced COM functionality by trancexxx, these interfaces are now accessible directly in AutoIt. I've rewritten the plugin as a native UDF which will work when compiled as x64 as well. I've attached the new UDF as well as updated plugin and UDF versions of my OSD Volume script. UDF Example: #include <_AudioEndpointVolume.au3> ; ## Get current volume levels $vol = _GetMasterVolumeLevel() ConsoleWrite("Get Vol Error: " & @error & @CRLF) ConsoleWrite("Volume: " & $vol & " (decibels)" & @CRLF) $vol = _GetMasterVolumeLevelScalar() ConsoleWrite("Get Vol Error: " & @error & @CRLF) ConsoleWrite("Volume: " & $vol & " (scalar)" & @CRLF) ; ## Set new volume levels ConsoleWrite("Set vol to -20db..." & @CRLF) _SetMasterVolumeLevel(-20) ConsoleWrite("Set Vol Error: " & @error & @CRLF) $vol = _GetMasterVolumeLevel() ConsoleWrite("Get Vol Error: " & @error & @CRLF) ConsoleWrite("Volume: " & $vol & " (decibels)" & @CRLF) ConsoleWrite("Set vol to scalar 30..." & @CRLF) _SetMasterVolumeLevelScalar(30) ConsoleWrite("Set Vol Error: " & @error & @CRLF) $vol = _GetMasterVolumeLevelScalar() ConsoleWrite("Get Vol Error: " & @error & @CRLF) ConsoleWrite("Volume: " & $vol & " (scalar)" & @CRLF) ; ## Get volume range information ConsoleWrite("Get range info..." & @CRLF) $aInfo = _GetVolumeRange() ConsoleWrite("Get Range Error: " & @error & @CRLF) ConsoleWrite("MinDB: " & $aInfo[0] & @CRLF) ConsoleWrite("MaxDB: " & $aInfo[1] & @CRLF) ConsoleWrite("Increment: " & $aInfo[2] & @CRLF) ; ## Set mute states ConsoleWrite("Set mute on..." & @CRLF) _SetMute(1) ConsoleWrite("Set Mute Error: " & @error & @CRLF) $mute = _GetMute() ConsoleWrite("Get Mute Error: " & @error & @CRLF) ConsoleWrite("Muted: " & $mute & @CRLF) Sleep(2000) ConsoleWrite("Set mute off..." & @CRLF) _SetMute(0) ConsoleWrite("Set Mute Error: " & @error & @CRLF) $mute = _GetMute() ConsoleWrite("Get Mute Error: " & @error & @CRLF) ConsoleWrite("Muted: " & $mute & @CRLF) ; ## Get volume step info ; ## Steps range from 0 to nStepCount - 1 ConsoleWrite("Get step info..." & @CRLF) $aInfo = _GetVolumeStepInfo() ConsoleWrite("Get Step Error: " & @error & @CRLF) ConsoleWrite("Current step: " & $aInfo[0] & @CRLF) ConsoleWrite("Total steps: 0 to " & $aInfo[1] - 1 & @CRLF) ConsoleWrite("Increase 5 steps..." & @CRLF) For $i = 1 To 5 _VolumeStepUp() Next $aInfo = _GetVolumeStepInfo() ConsoleWrite("Get Step Error: " & @error & @CRLF) ConsoleWrite("Current step: " & $aInfo[0] & @CRLF) ConsoleWrite("Decrease 2 steps..." & @CRLF) For $i = 1 To 2 _VolumeStepDown() Next $aInfo = _GetVolumeStepInfo() ConsoleWrite("Get Step Error: " & @error & @CRLF) ConsoleWrite("Current step: " & $aInfo[0] & @CRLF) OLD PLUGIN VERSION vista_vol_plugin.zip _AudioEndpointVolume.au3 VolumeOSD.zip VolumeOSD_plugin.zip1 point
-
simple bot does not working
SkysLastChance reacted to Tehran123 for a topic
Hello! Today I started to program my first bot with autoit. My problem is that the func. _search won´t start after running the program and pressing "+". HotKeySet ( "{+}","_start" ) HotKeySet ( "{#}","_pause" ) HotKeySet ( "{-}","_exit" ) Global $go = 0 Func _start() $go = 1 EndFunc Func _pause() $go = 0 EndFunc Func _exit() Exit EndFunc Func _search () MouseClick(MOUSE_CLICK_LEFT, 992, 766, 1, 10) MouseClick(MOUSE_CLICK_LEFT, 1221, 982, 1, 10) MouseClick(MOUSE_CLICK_LEFT, 1438, 736, 2, 10) Send ( "{ENTER}" ) Send ( "{ENTER}" ) MouseClick(MOUSE_CLICK_LEFT, 133, 184, 1, 10) EndFunc While 1 If $go = 1 Then _search() Else Sleep (10) EndIf WEnd Where is the problem? The program runs with out any problem..0 points