Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/12/2020 in all areas

  1. I'm mainly using two scripting languages: AutoIt and Perl. Today I'm mostly using AutoIt. In the past mostly Perl. I've long had an idea of integrating AutoIt and Perl to be able to generate and collect data in Perl scripts and display data in AutoIt GUIs. Over the past few months, I've been working on examples about ROT objects and their use in IPC techniques. I've tested the ideas with regard to AutoIt/Perl integration. It seems to work. Install PerlTo use the Perl programming language on a Windows PC, the program must be installed. I'm using ActivePerl from ActiveState. An alternative distribution is Strawberry Perl. ActivePerl seems to be the easiest to use. Strawberry Perl is more advanced and includes a complete C/C++ compiler. The interesting Perl module for AutoIt/Perl integration is the Win32::OLE module. It's the module that makes Perl a COM compatible programming language. Remember to add this module to your Perl installation. PerlScript Be careful not to confuse Perl with PerlScript. PerlScript is a Perl module developed by ActiveState and is only a small part of the ActivePerl package for Windows. PerlScript is an ActiveX Scripting Engine for the Perl language to use Perl to create dynamic content on the Microsoft web server (in the same way as it can be done with VBScript and JScript). First attemptServer.au3 (Examples\0) First attempt\): #include <GUIConstantsEx.au3> #include "..\..\Includes\IRunningObjectTable.au3" Example() Func Example() Local $hGui = GUICreate( "AutoIt/Perl integration", 300, 100 ) Local $sText = "Run Client.pl:" & @CRLF & _ "Open a Command Prompt in current folder." & @CRLF & _ "Key in ""Perl Client.pl"" and hit the Enter key." & @CRLF & _ "Or ""Perl Client.pl >Client.txt"" to get output in file." GUICtrlCreateLabel( $sText, 20, 20, 260, 60 ) GUISetState( @SW_SHOW, $hGui ) Local $sDataTransfer = "DataTransfer" ROT_RegisterObject( Default, $sDataTransfer ) ; Default => Object = Dictionary object While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete( $hGui ) EndFunc In the first attempt, we'll simply test whether the GetObject() function in a Perl script is at all able to recognize the ROT object (the dictionary object), and thus return something similar to a dictionary object. This is more or less the same as we did in the VBScript example in the bottom half of this post. So far, no data is stored in the ROT object. This Perl snippet copied from Win32::OLE can be used to test whether the ROT object is recognized. The code snippet prints object and class information: Win32::OLE->EnumAllObjects( sub { my $Object = shift; my $Class = Win32::OLE->QueryObjectType( $Object ); printf "Object = %s, Class = %s\n", $Object, $Class; } ); Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); Win32::OLE->EnumAllObjects( sub { my $Object = shift; my $Class = Win32::OLE->QueryObjectType( $Object ); printf "Object = %s, Class = %s\n", $Object, $Class; } ); Output: Object = Win32::OLE=HASH(0x71b5a8), Class = IDictionary It looks good. The ROT object is recognized as a kind of HASH object (sometimes called associative array, dictionary or map) of class IDictionary. This corresponds to the fact that the ROT object is actually a dictionary object. Data from AutoIt to PerlSimple dataNow we can store simple data in the ROT object this way. Server.au3 (Examples\1) AutoIt to Perl\1) Simple data\): Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object $oDataTransfer( "$iInt" ) = 123 $oDataTransfer( "$fFlt" ) = 123.456 $oDataTransfer( "$sStr" ) = "String" Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); print "$oObj->{'$iInt'}\n"; print "$oObj->{'$fFlt'}\n"; print "$oObj->{'$sStr'}\n"; Output: 123 123.456 String 1D arrayServer.au3 (Examples\1) AutoIt to Perl\2) 1D array\): Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object Local $aArray = [ 123, 123.456, "String" ] $oDataTransfer( "$aArray" ) = $aArray Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); print "@{$oObj->{'$aArray'}}\n"; Output: 123 123.456 String Note that internal data types of array elements are preserved. 2D arrayServer.au3 (Examples\1) AutoIt to Perl\2) 2D array\): Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object Local $aArray[1000][10] For $i = 0 To 1000 - 1 For $j = 0 To 10 - 1 $aArray[$i][$j] = $i & "/" & $j Next Next $oDataTransfer( "$aArray" ) = $aArray Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); foreach my $aRow ( @{$oObj->{'$aArray'}} ) { print "@{$aRow}\n"; } Output: 0/0 1/0 2/0 3/0 4/0 5/0 6/0 7/0 8/0 9/0 10/0 11/0 12/0 13/0 14/0 15/0 ... 0/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1 13/1 14/1 15/1 ... 0/2 1/2 2/2 3/2 4/2 5/2 6/2 7/2 8/2 9/2 10/2 11/2 12/2 13/2 14/2 15/2 ... 0/3 1/3 2/3 3/3 4/3 5/3 6/3 7/3 8/3 9/3 10/3 11/3 12/3 13/3 14/3 15/3 ... 0/4 1/4 2/4 3/4 4/4 5/4 6/4 7/4 8/4 9/4 10/4 11/4 12/4 13/4 14/4 15/4 ... 0/5 1/5 2/5 3/5 4/5 5/5 6/5 7/5 8/5 9/5 10/5 11/5 12/5 13/5 14/5 15/5 ... 0/6 1/6 2/6 3/6 4/6 5/6 6/6 7/6 8/6 9/6 10/6 11/6 12/6 13/6 14/6 15/6 ... 0/7 1/7 2/7 3/7 4/7 5/7 6/7 7/7 8/7 9/7 10/7 11/7 12/7 13/7 14/7 15/7 ... 0/8 1/8 2/8 3/8 4/8 5/8 6/8 7/8 8/8 9/8 10/8 11/8 12/8 13/8 14/8 15/8 ... 0/9 1/9 2/9 3/9 4/9 5/9 6/9 7/9 8/9 9/9 10/9 11/9 12/9 13/9 14/9 15/9 ... Rows and columns are swapped in the Perl array. Dict objServer.au3 (Examples\1) AutoIt to Perl\4) Dict obj\): Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object Local $oDict = ObjCreate( "Scripting.Dictionary" ) $oDict( "$iInt" ) = 123 $oDict( "$fFlt" ) = 123.456 $oDict( "$sStr" ) = "String" $oDataTransfer( "$oDict" ) = $oDict Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); print "${$oObj->{'$oDict'}}{'$iInt'}\n"; print "${$oObj->{'$oDict'}}{'$fFlt'}\n"; print "${$oObj->{'$oDict'}}{'$sStr'}\n"; Output: 123 123.456 String Data from Perl to AutoItSimple dataServer.au3 (Examples\2) Perl to AutoIt\1) Simple data\): #include "..\..\..\Includes\IRunningObjectTable.au3" Example() Func Example() Local $sDataTransfer = "DataTransfer" ROT_RegisterObject( Default, $sDataTransfer ) ; Default => Object = Dictionary object RunWait( @ComSpec & " /c " & "Perl Client.pl", "", @SW_HIDE ) Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object MsgBox( 0, "AutoIt/Perl integration", "$oDataTransfer( ""$iInt"" ) = " & $oDataTransfer( "$iInt" ) & @CRLF & _ "$oDataTransfer( ""$fFlt"" ) = " & $oDataTransfer( "$fFlt" ) & @CRLF & _ "$oDataTransfer( ""$sStr"" ) = " & $oDataTransfer( "$sStr" ) ) EndFunc Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); $oObj->{'$iInt'} = 123; $oObj->{'$fFlt'} = 123.456; $oObj->{'$sStr'} = "String"; Output: $oDataTransfer( "$iInt" ) = 123 $oDataTransfer( "$fFlt" ) = 123.456 $oDataTransfer( "$sStr" ) = String 1D arrayServer.au3 (Examples\2) Perl to AutoIt\2) 1D array\): #include "..\..\..\Includes\IRunningObjectTable.au3" #include <Array.au3> Example() Func Example() Local $sDataTransfer = "DataTransfer" ROT_RegisterObject( Default, $sDataTransfer ) ; Default => Object = Dictionary object RunWait( @ComSpec & " /c " & "Perl Client.pl", "", @SW_HIDE ) Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object Local $aArray = $oDataTransfer( "$aArray" ) _ArrayDisplay( $aArray ) EndFunc Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); my @aArray = ( 123, 123.456, "String" ); $oObj->{'$aArray'} = \@aArray; Output: 123 123.456 String 2D arrayServer.au3 (Examples\2) Perl to AutoIt\3) 2D array\): #include "..\..\..\Includes\IRunningObjectTable.au3" #include <Array.au3> Example() Func Example() Local $sDataTransfer = "DataTransfer" ROT_RegisterObject( Default, $sDataTransfer ) ; Default => Object = Dictionary object RunWait( @ComSpec & " /c " & "Perl Client.pl", "", @SW_HIDE ) Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object Local $aArray = $oDataTransfer( "$aArray" ) _ArrayDisplay( $aArray ) EndFunc Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); my @aArray; for( my $i = 0; $i < 10; $i++ ) { for( my $j = 0; $j < 1000; $j++ ) { $aArray[$i][$j] = $j . "/" . $i; } } $oObj->{'$aArray'} = \@aArray; Output: 0/0 0/1 0/2 0/3 0/4 0/5 0/6 0/7 0/8 0/9 1/0 1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8 1/9 2/0 2/1 2/2 2/3 2/4 2/5 2/6 2/7 2/8 2/9 3/0 3/1 3/2 3/3 3/4 3/5 3/6 3/7 3/8 3/9 4/0 4/1 4/2 4/3 4/4 4/5 4/6 4/7 4/8 4/9 5/0 5/1 5/2 5/3 5/4 5/5 5/6 5/7 5/8 5/9 6/0 6/1 6/2 6/3 6/4 6/5 6/6 6/7 6/8 6/9 7/0 7/1 7/2 7/3 7/4 7/5 7/6 7/7 7/8 7/9 8/0 8/1 8/2 8/3 8/4 8/5 8/6 8/7 8/8 8/9 9/0 9/1 9/2 9/3 9/4 9/5 9/6 9/7 9/8 9/9 10/0 10/1 10/2 10/3 10/4 10/5 10/6 10/7 10/8 10/9 11/0 11/1 11/2 11/3 11/4 11/5 11/6 11/7 11/8 11/9 12/0 12/1 12/2 12/3 12/4 12/5 12/6 12/7 12/8 12/9 13/0 13/1 13/2 13/3 13/4 13/5 13/6 13/7 13/8 13/9 14/0 14/1 14/2 14/3 14/4 14/5 14/6 14/7 14/8 14/9 15/0 15/1 15/2 15/3 15/4 15/5 15/6 15/7 15/8 15/9 ... Dict objServer.au3 (Examples\2) Perl to AutoIt\4) Dict obj\): #include "..\..\..\Includes\IRunningObjectTable.au3" #include <Array.au3> Example() Func Example() Local $sDataTransfer = "DataTransfer" ROT_RegisterObject( Default, $sDataTransfer ) ; Default => Object = Dictionary object RunWait( @ComSpec & " /c " & "Perl Client.pl", "", @SW_HIDE ) Local $oDataTransfer = ObjGet( $sDataTransfer ) ; Dictionary object Local $aDict = $oDataTransfer( "$aDict" ) _ArrayDisplay( $aDict ) EndFunc Client.pl: use strict; use Win32::OLE; my $oObj = Win32::OLE->GetObject( "DataTransfer" ); my %oDict = ( '$iInt' => 123, '$fFlt' => 123.456, '$sStr' => "String" ); my @aDict = ( [ keys %oDict ], [ values %oDict ] ); $oObj->{'$aDict'} = \@aDict; Output: $iInt 123 $fFlt 123.456 $sStr String 7z-fileThe 7z-file contains source code for the UDF 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. AutoItAndPerl.7z
    2 points
  2. Au3toCmd --- Avoid false virus positives Since many virus scanners sometimes prevent a "compiled autoit EXE" from being executed as "false positive", the "*.A3X" format is a suitable format to avoid this problem. See here for more information. In order to simplify this procedure, I wrote the Au3toCmd script. Here a *.Cmd file is generated from a *.Au3 file. The necessary files Autoit3.exe and *.A3x are added to the "*.Cmd" file as "alternate data streams" "Base64" encoded data. Now the Autoit Script can be called by clicking on the cmd file and the anti-virus scanners do not recognize the "false positive". If the short-term flashing of the CMD window bothers you, you can click the desktop shutcut that runs in a minimized window. Unfortunately, because the "alternate data streams", this CMD file cannot be distributed via FTP or email. Only a USB sti ck or removable disk formatted with NTFS can be used. As the new version now uses Base64 data instead of ADS, this statement is out of date. For reasons of compatibility, the old version was sunk into the spoiler here. The script can be called with a file name of an AU3 script as a parameter. If no name is entered, a query is made. For more information, see the header of the script. Suggestions, improvements and bug reports are welcome. Here the versions using base64 data Version: 2022.05.12 (Support blanks in pathnames) Version: 2022.06.23 (Support release candidates. Changed @CrLf to @Lf. Annual cleaning. Optimized #AutoIt3Wrapper handling) Version: 2022.07.22 (Support scripts with the same name but different content in different directories) Version: 2022.07.27 (Support blanks in usernames) Au3toCmd.au3 Version: 2022.09.01 (Optimized annual cleaning) Au3toCmd.au3
    1 point
  3. This is an update of the old Automating Windows Explorer example. The update includes Desktop automation. However, Windows XP code has been removed. ThreadsOther threads related to File/Windows Explorer: Implementing Windows Explorer right pane Implementing Windows Explorer address bar Enumerating and Browsing the Desktop Some of these threads are very old. I'm considering updating some of the examples: Remove Windows XP code. Implement some of the code in other ways. Enumerating and Browsing the Desktop is important to me personally because it was the first time I used the ObjCreateInterface() function. The first version of the example was based on _AutoItObject_WrapperCreate() from the AutoItObject UDF. Then I was told that you can use ObjCreateInterface() instead. Of course I had to try. Automating File/Windows Explorer and DesktopAutomating File/Windows Explorer The old example contains a description of the techniques for automating File/Windows Explorer. The techniques are based on COM interfaces. Initially, it's about getting an IShellBrowser interface based on a File/Windows Explorer window handle. An IDispatch interface for the window is important for creating the IShellBrowser interface. Through the IShellBrowser interface, you can generate a large number of interfaces that can be used to implement the automation functions. Automating DesktopBilgus figured out how to get an IDispatch interface for the Desktop in this post: $oIShellWindows.FindWindowSW( Null, Null, $SWC_DESKTOP, $hWnd, $SWFO_NEEDDISPATCH, $pIDispatch ) This is the part of the old code in the GetIShellBrowser() function that needs to be updated to include the Desktop: ; Get an IWebBrowserApp object for each window ; This is done in two steps: ; 1. Get an IDispatch object for the window ; 2. Get the IWebBrowserApp interface ; Check if it's the right window Local $pIDispatch, $oIDispatch Local $pIWebBrowserApp, $oIWebBrowserApp, $hWnd For $i = 0 To $iWindows - 1 $oIShellWindows.Item( $i, $pIDispatch ) If $pIDispatch Then $oIDispatch = ObjCreateInterface( $pIDispatch, $sIID_IDispatch, $dtag_IDispatch ) $oIDispatch.QueryInterface( $tRIID_IWebBrowserApp, $pIWebBrowserApp ) If $pIWebBrowserApp Then $oIWebBrowserApp = ObjCreateInterface( $pIWebBrowserApp, $sIID_IWebBrowserApp, $dtag_IWebBrowserApp ) $oIWebBrowserApp.get_HWND( $hWnd ) If $hWnd = $hExplorer Then ExitLoop EndIf EndIf Next And here the code to include the Desktop is added: ; Get an IWebBrowserApp object for each window ; This is done in two steps: ; 1. Get an IDispatch object for the window ; 2. Get the IWebBrowserApp interface ; Check if it's the right window Local $pIDispatch, $oIDispatch, $hRes Local $pIWebBrowserApp, $oIWebBrowserApp, $hWnd For $i = 0 To $iWindows $hRes = $i < $iWindows ? $oIShellWindows.Item( $i, $pIDispatch ) _ : $oIShellWindows.FindWindowSW( Null, Null, $SWC_DESKTOP, $hWnd, $SWFO_NEEDDISPATCH, $pIDispatch ) If $pIDispatch Then $oIDispatch = ObjCreateInterface( $pIDispatch, $sIID_IDispatch, $dtag_IDispatch ) $oIDispatch.QueryInterface( $tRIID_IWebBrowserApp, $pIWebBrowserApp ) If $pIWebBrowserApp Then $oIWebBrowserApp = ObjCreateInterface( $pIWebBrowserApp, $sIID_IWebBrowserApp, $dtag_IWebBrowserApp ) $oIWebBrowserApp.get_HWND( $hWnd ) If $hWnd = $hExplorer Then ExitLoop EndIf EndIf Next The For loop runs an extra round if a File/Explorer Window has not been identified. In this last loop, the FindWindowSW() method returns a window corresponding to the Desktop. Here, the method always returns the Program Manager window. a consequence of this implementation is that if you specify a non-existent window as a parameter to the GetIShellBrowser() function, then the function will return the Program Manager window. Thus, the Program Manager window is the default window for the function. The IDispatch interface is the important thing in terms of automating the Desktop. Then all the functions used in connection with a File/Windows Explorer window can also be used in connection with the Desktop. Except for a few functions that are not relevant for the Desktop. Functions The automation functions are coded in FileExplorer.au3. The functions are implemented using a number of Shell API functions and Shell COM interfaces coded in ShellFunctions.au3 and ShellInterfaces.au3. The old example contains a list of implemented functions. New functions GetSortColumns() GetSortColumnsEx() SetSortColumns() Examples The 7z-file contains examples for automating the Desktop and a File/Windows Explorer window. These are the same examples as in this post. Note that the examples GetFiles.au3 and GetFolders.au3 also show how to make a list of selected files and folders. Note that the GetSetIconView.au3 example can change the order of icons on the Desktop. If you don't want this, run this example only in a File/Windows Explorer window. The GUI application that was used to demonstrate the features in the old version is not included. The small examples seems to be much more useful. This post contains new examples. In both the old and the new post, the examples are shown for a File/Windows Explorer window. But the 7z-file contains similar examples for the Desktop. Forum examplesThis is a list of the most interesting examples in the old thread: The original collection of small examples Automate a file search with UI Automation code. The question that led to this answer was asked in a slightly earlier post. Execute a function on a double-click in empty space of the listview. Based on UI Automation code. Here the question was asked somewhat earlier. UI Automation code to make a selected item visible by scrolling the listview up or down 7z-fileThe 7z-file contains source code for the UDF 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. FileExplorerAndDesktop.7z
    1 point
  4. This is a response due to a PM. With UI Automation code you can generally automate tasks that a user can perform. But it has to be a real user and not just the System account. There are several examples that show that this is not possible. It's possible to save a file downloaded with IE through UIA code. But not with the System account that you want.
    1 point
  5. The first post (ROT objects section) and the third post (last section) have been updated. New 7z-file at bottom of first post.
    1 point
  6. @crazycrash Seems like innerText is a property, not an attribute. Try this and let me know how it works for you -- #include "wd_core.au3" #include "wd_helper.au3" Local $sDesiredCapabilities, $sSession, $sElement ;~ Local $sImageXpath = "//a[@rel='theater' and @data-ploi]" ;~ Local $sContentXpath = "//ancestor::div[@class='_3x-2']/preceding-sibling::div[contains(@class,'userContent')]" Local $sContentXpath2 = "//div[@data-testid='post_message' and contains(@class, '_5pbx')]" Local $sJavascript = "window.scrollTo(0, document.body.scrollHeight)" SetupGecko() _WD_Startup() $sSession = _WD_CreateSession($sDesiredCapabilities) If @error = $_WD_ERROR_Success Then ConsoleWrite("Starting extraction: " & @CRLF) _WD_Navigate($sSession, "https://www.facebook.com/AstrophysicsAndAstronomy/") ; force page to load dynamic content For $i = 1 To 3 _WD_ExecuteScript($sSession, $sJavascript) Next _WD_WaitElement($sSession, $_WD_LOCATOR_ByXPath, $sContentXpath2, 2000) $aElements = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, $sContentXpath2, Default, True) For $i = 0 To UBound($aElements, 1) - 1 $sComment = _WD_ElementAction($sSession, $aElements[$i], 'property', 'innerText') ConsoleWrite($sComment & @crlf & "===============" & @CRLF) Sleep(350) Next EndIf _WD_DeleteSession($sSession) _WD_Shutdown() Func SetupChrome() _WD_Option('Driver', 'chromedriver.exe') _WD_Option('Port', 9515) _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\chrome.log"') $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "excludeSwitches": [ "enable-automation"], "useAutomationExtension": false }}}}' EndFunc Func SetupGecko() _WD_Option('Driver', 'geckodriver.exe') _WD_Option('DriverParams', '--log trace') _WD_Option('Port', 4444) $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"browserName": "firefox", "acceptInsecureCerts":true}}}' EndFunc
    1 point
×
×
  • Create New...