Jump to content

Recommended Posts

Hello everyone,

I've created a UDF for basic communication with SSH servers. I know there is already such a UDF, but I wasn't satisfied with it for my purpose, so I created a new one.

This UDF also acts as a wrapper for the plink executable. Its essential functions are _SSHConnect, _SSHSend, _SSHRecv and _SSHCloseSocket.

It does support multiple simultaneous connections and aims to be pretty robust. Feel free to share your opinions :)

Two of the included examples use a slightly modified version of Vintage Terminal by @Chimp

Spoiler
#include-once

#include <Constants.au3>
#include <Timers.au3>
#include <Array.au3>

OnAutoItExitRegister("__internal_closeAllSockets")

; #INDEX# =======================================================================================================================
; Title .........: SSH_UDF <ssh.au3>
; Udf Version....: 1.0 (09-2021)
; AutoIt Version : 3.3.14.5
; Language ......: English
; Description ...: Provides basic functionality to connect and communicate with SSH servers
; Author(s) .....: p4sCh
; Exe(s) ........: plink.exe; plink.exe is distributed under MIT License. See LICENSE.txt
; ===============================================================================================================================

; #PUBLIC FUNCTIONS# ============================================================================================================
; _SSHConnect       <Essential>
; _SSHLogin         <Optional>
; _SSHSend          <Essential>
; _SSHRecv          <Essential>
; _SSHCloseSocket   <Essential>
; _SSHSetConfig     <Optional>
; _SSHGetConfig     <Optional>
; _SSHSetPS1        <Misc>
; ===============================================================================================================================

; #INTERNAL FUNCTIONS# ==========================================================================================================
; __internal_SSHRecv
; __internal_applyInputEcho
; __internal_sanitizeOutput
; __internal_addSocket
; __internal_removeSocket
; __internal_isSocket
; __internal_getSocketIdx
; __internal_closeSocketAndReturn
; __internal_closeAllSockets
; hostToIP
; isValidIPv4
; isValidIPv6
; ===============================================================================================================================

; #CONSTANTS# ===================================================================================================================
Global Const $SSH_HOST_KEY_AUTO_ACCEPT = 0, $SSH_HOST_KEY_AUTO_ACCEPT_AND_STORE = 1, _
    $SSH_HOST_KEY_ABORT_IF_UNKNOWN = 2, $SSH_HOST_KEY_INTERACTIVE = 3
; ===============================================================================================================================

; #VARIABLES# ===================================================================================================================
Global $__plinkFolder = @ScriptDir & "\"
Global $__plinkExe = "plink.exe"
Global $__plinkFullPath = $__plinkFolder & $__plinkExe

Global $__echoLoginEnabled=True, $__stripBracketedPasteModeANSICodes=True, _
       $__stripPS1BeforeBell=True, $__stripANSIColorCodes=False, $__sanitizePlinkStderr=False

Dim $__socket[1], $__echoStr[1]
_ArrayPop($__socket)
_ArrayPop($__echoStr)
; ===============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHConnect
; Description ...: Establishes a connection with a ssh server
; Parameters ....: $host        - IPv4, IPv6 or hostname
;                  $login       - username
;                  $passwd      - password
;                  $port        - ssh port (default 22)
;                  $sshKeyFingerprint - how should _SSHConnect react when ssh key fingerprint of server is unknown? options are:
;                      $SSH_HOST_KEY_AUTO_ACCEPT          : accept ssh host key (do not store key in cache) (default)
;                      $SSH_HOST_KEY_AUTO_ACCEPT_AND_STORE: accept ssh host key and store in cache (registry) for future
;                      $SSH_HOST_KEY_ABORT_IF_UNKNOWN     : reject ssh host key if unknown (and disconnect)
;                      $SSH_HOST_KEY_INTERACTIVE          : don't answer when prompted, let user decide
; Return values .: Success      - Returns socket id greater than zero
;                               - Returns zero when connection was established and then canceled
;                                 (because ssh key fingerprint was unknown and $SSH_HOST_KEY_ABORT_IF_UNKNOWN was used)
;                  Failure      - Returns error code less than zero
; Author ........: p4sCh
; Modified.......:
; Remarks .......: Login(username) and password don't have to be passed to this function. You can also login when prompted.
;                  You can use _SSHLogin for logging in when prompted.
; Related .......: _SSHCloseSocket, _SSHLogin
; ===============================================================================================================================
Func _SSHConnect($host, $login="", $passwd="", $port=22, $sshKeyFingerprint=$SSH_HOST_KEY_AUTO_ACCEPT)
    $host = hostToIP($host)
    If $host == "" Then Return -1
    If Not FileExists($__plinkFullPath) Then
        ConsoleWriteError("SSH UDF: Path to plink executable is not valid! Path: "&$__plinkFullPath&@LF)
        Return -2
    EndIf

    Local $plinkCmd = $__plinkFullPath & " -P " & $port
    If $passwd <> "" Then $plinkCmd &= ' -pw "' & $passwd & '"'
    If Not StringIsSpace($login) Then
        $plinkCmd &= " " & $login & "@" & $host
    Else
        $plinkCmd &= " " & $host
    EndIf

    Local $socket = Run($plinkCmd, $__plinkFolder, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD + $STDERR_CHILD)
    If @error Then Return -3

    Local $sIdx = __internal_addSocket($socket)
    If $sshKeyFingerprint <> $SSH_HOST_KEY_INTERACTIVE Then
        Local $timeout = _Timer_Init()
        Local $recv = ""
        Do
            $recv = __internal_SSHRecv($socket, False)
            If @error > 1 Then Return __internal_closeSocketAndReturn($socket, -4)
            If $recv <> "" Then
                If $__echoLoginEnabled Then $__echoStr[$sIdx] &= $recv
                If StringInStr($recv, "store key in cache?") Then
                    Local $success, $answer
                    If $sshKeyFingerprint = $SSH_HOST_KEY_AUTO_ACCEPT_AND_STORE Then
                        $answer = "y"&@CR
                    ElseIf $sshKeyFingerprint == $SSH_HOST_KEY_AUTO_ACCEPT Then
                        $answer = "n"&@CR
                    ElseIf $sshKeyFingerprint == $SSH_HOST_KEY_ABORT_IF_UNKNOWN Then
                        $answer = @CR
                    Else
                        Return __internal_closeSocketAndReturn($socket, -5)
                    EndIf
                    If $__echoLoginEnabled Then $__echoStr[$sIdx] &= $answer & @LF
                    $success = _SSHSend($socket, $answer)
                    If Not $success Then Return __internal_closeSocketAndReturn($socket, -6)
                    If $sshKeyFingerprint == $SSH_HOST_KEY_ABORT_IF_UNKNOWN Then Return __internal_closeSocketAndReturn($socket, 0)
                EndIf
            Else
                Sleep(15)
            EndIf
        Until $recv <> "" Or _Timer_Diff($timeout) > 5500
    EndIf

    Return $socket
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHLogin
; Description ...: If login or password was not passed to _SSHConnect, then _SSHLogin can be used
;                  to pass login information to interactive prompt
; Parameters ....: $host        - ssh socket
;                  $login       - username
;                  $passwd      - password
; Return values .: Success      - Returns True
;                  Failure      - Returns False
; Author ........: p4sCh
; Modified.......:
; Remarks .......: This function can be used when prompted login and/or password.
;                  This function might not work correctly in every case.
; Related .......: _SSHConnect
; ===============================================================================================================================
Func _SSHLogin($socket, $login="", $passwd="")
    Local $sIdx = __internal_getSocketIdx($socket)
    If $sIdx < 0 Then Return False
    Local $loginEntered = False, $passwdEntered = False, $success = False
    Local $timeout = _Timer_Init()
    Local $i = 0
    Do
        Local $recv
        If $i == 0 Then
            $recv = $__echoStr[$sIdx]
        Else
            $recv = __internal_SSHRecv($socket, False)
            If @error > 1 Then Return False
        EndIf
        If StringInStr($recv,"login as:") Then
            If $login == "" Or $loginEntered Then Return False
            If $__echoLoginEnabled Then
                If $i <> 0 Then $__echoStr[$sIdx] &= $recv
                $__echoStr[$sIdx] &= $login & @LF
            EndIf
            Local $ret = _SSHSend($socket, $login & @LF)
            If Not $ret Then Return False
            $loginEntered = True
        ElseIf StringInStr($recv,"password:") Then
            If $passwd == "" Or $passwdEntered Then Return False
            If $__echoLoginEnabled Then
                If $i <> 0 Then $__echoStr[$sIdx] &= $recv
                $__echoStr[$sIdx] &= "****" & @LF
            EndIf
            Local $ret = _SSHSend($socket, $passwd & @LF)
            If Not $ret Then Return False
            $passwdEntered = True
        Else
            If $i == 0 Then
                $i = 1
                ContinueLoop
            EndIf
            $__echoStr[$sIdx] &= $recv
            If $recv <> "" And ($loginEntered Or $passwdEntered) Then
                $success = True
                ExitLoop
            EndIf
        EndIf
        Sleep(10)
        $i += 1
    Until _Timer_Diff($timeout) > 5500
    Return $success
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHSend
; Description ...: Send data to the ssh session.
; Parameters ....: $socket      - ssh socket
;                  $data        - string to send
; Return values .: Success      - Returns True
;                  Failure      - Returns False
; Author ........: p4sCh
; Modified.......:
; Remarks .......: When communicating with plink directly (e.g. ssh host key prompt) enter commands by appending @CR.
;                  When communicating with ssh server (everything else) often both @CR and @LF work for entering commands.
; Related .......: _SSHRecv
; ===============================================================================================================================
Func _SSHSend($socket, $data)
    If Not __internal_isSocket($socket) Then Return False
    StdinWrite($socket, $data)
    If @error Then Return False
    Return True
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHRecv
; Description ...: Receive data returned from plink (data source might be plink itself or ssh session)
; Parameters ....: $socket      - ssh socket
; Return values .: Success      - Returns data read from stdout
;                  Failure      - Sets @error greater than zero.
;                      @error=1:  Returns data read from stderr (can be important)
;                      @error=2:  Returns empty string. Socket invalid
;                      @error=3:  Returns empty string. Socket invalid OR stdout and stderr not available OR other error
;                                 Probably means you got disconnected from the ssh session
; Author ........: p4sCh
; Modified.......:
; Remarks .......:
; Related .......: _SSHSend
; ===============================================================================================================================
Func _SSHRecv($socket)
    Local $recv = __internal_SSHRecv($socket)
    SetError(@error)
    Return $recv
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHCloseSocket
; Description ...: Close a ssh socket returned by _SSHConnect
; Parameters ....: $socket      - ssh socket (ByRef)
; Return values .: N/A
; Author ........: p4sCh
; Modified.......:
; Remarks .......: This function sets passed ssh socket to zero
; Related .......: _SSHConnect
; ===============================================================================================================================
Func _SSHCloseSocket(ByRef $socket)
    If Not __internal_isSocket($socket) Then Return
    StdioClose($socket)
    ProcessClose($socket)
    __internal_removeSocket($socket)
    $socket = 0
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHSetConfig
; Description ...: Set ssh configuration values
; Parameters ....: $variableName    - name of the variable to be changed
;                  $value           - new value for that variable
; Return values .: Success          - Returns True. New value set
;                  Failure          - Returns False. Either non-existent variable name or wrong value type
; Author ........: p4sCh
; Modified.......:
; Remarks .......: Valid variableName:[value-type] pairs are:
;                  "plinkFolder":[String]         - Path where plink executable is located (default: @ScriptDir & "\")
;                  "plinkExe":[String]            - plink executable name (default: plink.exe)
;                  "echoLoginEnabled":[Bool]      - Receive full login procedure via _SSHRecv (default: True)
;                  "stripBracketedPasteModeANSICodes":[Bool] - Remove Bracketed-Paste-Mode ANSI Codes from ssh output
;                                                              These Codes are ESC[?2004h and ESC[?2004l (default: True)
;                  "stripPS1BeforeBell":[Bool]    - If found ESC[0; ANSI Code and then Bell-Character in one line of ssh output,
;                                                   these characters and everything in between get removed (default: True)
;                  "stripANSIColorCodes":[Bool]   - Removes ANSI Color Codes and ANSI SGR Codes from _SSHRecv (default: False)
;                  "sanitizePlinkStderr":[Bool]   - Applies sanitize functions (stripBracketedPasteModeANSICodes,
;                                                   stripPS1BeforeBell, stripANSIColorCodes) also to plinks stderr
;                                                   instead of only to its stdout (default: False)
; Related .......: _SSHGetConfig
; ===============================================================================================================================
Func _SSHSetConfig($variableName, $value)
    If $variableName == "" Or $value == "" Then Return False
    If StringLeft($variableName, 1) == "$" Then $variableName = StringRight($variableName, StringLen($variableName) - 1)

    Switch $variableName
        Case "plinkFolder", "plinkExe"
            If Not IsString($value) Then
                ConsoleWriteError("SSH Config error: Could not change $"&$variableName&". Wrong value type, String expected!"&@LF)
                Return False
            ElseIf $variableName == "plinkFolder" Then
                If StringRight($value, 1) <> "\" And StringRight($value, 1) <> "/" Then $value &= "\"
                $__plinkFullPath = $value & $__plinkExe
            ElseIf $variableName == "plinkExe" Then
                $__plinkFullPath = $__plinkFolder & $value
            EndIf
        Case "echoLoginEnabled", "stripBracketedPasteModeANSICodes", "stripPS1BeforeBell", "stripANSIColorCodes", _
             "sanitizePlinkStderr"
            If Not IsBool($value) Then
                ConsoleWriteError("SSH Config error: Could not change $"&$variableName&". Wrong value type, Bool expected!"&@LF)
                Return False
            EndIf
        Case "socket", "echoStr"
            Return False
    EndSwitch
    If Not Assign("__" & $variableName, $value, $ASSIGN_EXISTFAIL) Then
        ConsoleWriteError("SSH Config error: Variable $"&$variableName&" does not exist!"&@LF)
        Return False
    EndIf
    Return True
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHGetConfig
; Description ...: Get ssh configuration values
; Parameters ....: $variableName    - name of the variable to be returned
; Return values .: Success          - Returns value of the requested variable
;                  Failure          - Returns empty string and sets @error to non-zero
; Author ........: p4sCh
; Modified.......:
; Remarks .......: Names of returnable variables are: "plinkFolder", "plinkExe", "echoLoginEnabled",
;                  "stripBracketedPasteModeANSICodes", "stripPS1BeforeBell", "stripANSIColorCodes", "sanitizePlinkStderr"
;                  For explanation of these variables see _SSHSetConfig
; Related .......: _SSHSetConfig
; ===============================================================================================================================
Func _SSHGetConfig($variableName)
    If StringLeft($variableName, 1) == "$" Then $variableName = StringRight($variableName, StringLen($variableName) - 1)
    Local $value = Eval("__" & $variableName)
    Return SetError(@error, 0, $value)
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _SSHSetPS1
; Description ...: Changes the prompt string on the ssh server
; Parameters ....: $socket      - ssh socket
;                  $PS1         - new prompt string
; Return values .: Success      - Returns True
;                  Failure      - Returns False (might return True if 'export PS1="x"' command does not work on ssh server)
; Author ........: p4sCh
; Modified.......:
; Remarks .......: Works by executing the command 'export PS1="x"' where x is the string ($PS1) passed to the function
; Related .......: N/A
; ===============================================================================================================================
Func _SSHSetPS1($socket, $PS1 = "SSH: ")
    Return _SSHSend($socket, 'export PS1="' & $PS1 & '"' & @CR)
EndFunc

; #INTERNAL FUNCTIONS# ==========================================================================================================
; Author ........: p4sCh (except for isValidIPv4 and isValidIPv6)
; ..............->
Func __internal_SSHRecv($socket, $addEcho=True, $peek=False)
    Local $output = ""
    Local $sIdx = __internal_getSocketIdx($socket)
    If $sIdx < 0 Then Return SetError(2, 0, $output)
    Local $stdoutErr = False
    $output = StdoutRead($socket, $peek)
    If $output == "" Then
        If @error Then $stdoutErr = True
        If $addEcho Then __internal_applyInputEcho($output, $sIdx)
        $output &= StderrRead($socket, $peek)
        If $output <> "" Then
            If $__sanitizePlinkStderr Then __internal_sanitizeOutput($output)
            Return SetError(1, 0, $output)
        ElseIf @error And $stdoutErr == True Then
            Return SetError(3, 0, $output)
            EndIf
    Else
        __internal_sanitizeOutput($output)
        If $addEcho Then __internal_applyInputEcho($output, $sIdx)
    EndIf
    Return $output
EndFunc

Func __internal_applyInputEcho(ByRef $str, $idx)
    $str = $__echoStr[$idx] & $str
    $__echoStr[$idx] = ""
EndFunc

Func __internal_sanitizeOutput(ByRef $str)
    If $__stripBracketedPasteModeANSICodes Then
        $str = StringReplace($str,"�[?2004h","")
        $str = StringReplace($str,"�[?2004l"&@CR,"")
    EndIf
    If $__stripPS1BeforeBell Then
        If StringInStr($str, "�") Then
            Local $lines = StringSplit($str, @CRLF)
            Local $p1, $p2
            For $i=1 To $lines[0]
                $p1 = StringInStr($str,"�]0;")
                If $p1 <> 0 Then
                    $p2 = StringInStr($str, "�", 1, 1, $p1)
                    If $p2 <> 0 Then
                        $str = StringLeft($str, $p1-1) & StringRight($str, StringLen($str) - $p2)
                    EndIf
                EndIf
            Next
        EndIf
    EndIf
    If $__stripANSIColorCodes Then
        ; Matching Pattern: ESC\[[0-107][;0-107][;0-255]m               ; leading zeros are matched
        ; Matches ANSI Codes: SGR, 3-bit color, 4-bit color and 8-bit color
        $str = StringRegExpReplace($str,"�\[([0-1]0[0-7]|\d?\d)?(;[0-1]0[0-7]|;\d?\d)?(;[0-1]?\d?\d|;(0|2)[0-5][0-5])?m", "")
        ; Matching Pattern: ESC\[(38|48);2;[0-255];[0-255];[0-255]m     ; leading zeros are matched
        ; Matches ANSI Codes: True Color (24-bit)
        $str = StringRegExpReplace($str,"�\[(38|48);2;([0-1]?\d?\d|(0|2)[0-5][0-5]);([0-1]?\d?\d|(0|2)[0-5][0-5]);([0-1]?\d?\d|(0|2)[0-5][0-5])m","")
    EndIf
EndFunc

Func __internal_addSocket($socket, $echoStr = "")
    ReDim $__socket[UBound($__socket) + 1]
    ReDim $__echoStr[UBound($__echoStr) + 1]
    $__socket[UBound($__socket) - 1] = $socket
    $__echoStr[UBound($__echoStr) - 1] = $echoStr
    Return UBound($__socket) - 1
EndFunc

Func __internal_removeSocket($socket)
    Local $idx = _ArraySearch($__socket, $socket)
    If $idx >= 0 Then
        If _ArrayDelete($__socket, $idx) >= 0 Then
            _ArrayDelete($__echoStr, $idx)
            Return True
        EndIf
    EndIf
    Return False
EndFunc

Func __internal_isSocket($socket)
    If _ArraySearch($__socket, $socket) >= 0 Then Return True
    Return False
EndFunc

Func __internal_getSocketIdx($socket)
    Return _ArraySearch($__socket, $socket)
EndFunc

Func __internal_closeSocketAndReturn($socket, $retValue)
    _SSHCloseSocket($socket)
    Return $retValue
EndFunc

Func __internal_closeAllSockets()
    Local $i
    For $i=0 To UBound($__socket) -1
        StdioClose($__socket[$i])
        ProcessClose($__socket[$i])
    Next
    ReDim $__socket[1]
    ReDim $__echoStr[1]
    _ArrayPop($__socket)
    _ArrayPop($__echoStr)
EndFunc

Func hostToIP($host)
    If StringIsSpace($host) Then
        Return ""
    ElseIf isValidIPv4($host) Or isValidIPv6($host) Then
        Return $host
    Else
        TCPStartup()
        Local $IP = TCPNameToIP($host)
        If @error Then ConsoleWriteError("SSH UDF: Could not resolve IP/Domain: " & $host & @LF)
        TCPShutdown()
        Return $IP
    EndIf
EndFunc

; Source: jchd https://www.autoitscript.com/forum/topic/163160-regular-expression-to-confirm-an-ipv4-address/?do=findComment&comment=1188014
Func isValidIPv4($ipv4)
    Return StringRegExp($ipv4, "^(?:[1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])){3}$", 0)
EndFunc

; Source: James https://www.autoitscript.com/forum/topic/144168-validate-ipv6-address/
Func isValidIPv6($ipv6)
    Return StringRegExp($ipv6, "^(([\da-f]{0,4}:{0,2}){1,8})$", 0)
EndFunc
; ===============================================================================================================================

 

Download

The download includes ssh.au3 (UDF), plink.exe (necessary), vintage terminal and code examples:

SSH UDF.zip

Edited by p4sCh
grammar
Link to post
Share on other sites
On 9/30/2021 at 3:07 PM, gcriaco said:

It works fine. Many thanks and compliments!

Thank you 😊

On 10/2/2021 at 9:45 AM, Chimp said:

Hi @p4sCh, good job!

thanks for sharing :)

Thanks for providing the vintage terminal. It really took the examples to another level!

You might want to consider to update the original vintage terminal thread with the modified version from this UDF.

It does have some bug fixes, new features and should have noticeable better performance.

On 10/1/2021 at 5:11 AM, JiBe said:

this UDF SSH - AutoIt Example Scripts - AutoIt Forums (autoitscript.com) support multiple simultaneous connections.

 

I know :). And it supports many plink settings which can not be adjusted in this UDF. I had different reasons to make another SSH UDF.

Link to post
Share on other sites

Hi,

Thanks for sharing but ...

I wonder why you use an external app to create an SSH cleient.

While W10 has this out of the box using the SSH command

usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]
           [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
           [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
           [-i identity_file] [-J [user@]host[:port]] [-L address]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-Q query_option] [-R address] [-S ctl_path] [-W host:port]
           [-w local_tun[:remote_tun]] destination [command]

Which also integrates in Windows Terminal 

https://docs.microsoft.com/en-us/windows/terminal/tutorials/ssh

 

Link to post
Share on other sites
Posted (edited)
13 hours ago, ptrex said:

Hi,

Thanks for sharing but ...

I wonder why you use an external app to create an SSH cleient.

While W10 has this out of the box using the SSH command

Just because I didn't knew about this feature 😅
Very interesting, thank you. At the moment I have little time but I consider changing the UDF to use this method primarily or as alternative to plink. Would be nice to drop the additional executable.

Edit: Looks like this command is only available from Win10 (Version 1709+). So on an older OS you would have to use plink instead.

Edited by p4sCh
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By water
      I have started to rewrite the PowerPoint UDF similar to the Word, Excel and Outlook UDF. The new UDF will not be compatible with the existing one.
      I will add examples, documentation, a section in the wiki etc.
      So far the following functions have been coded - more are on the ToDo list.
      _PPT_Open: Open a connection to a running instance of PowerPoint or start a new one _PPT_Close: Close a PowerPoint instance _PPT_CommentAdd: Add a Comment anywhere on a Slide or connected to a Shape (version 1.5.0.0 2021-08-31) _PPT_CommentDelete: Delete a single Comment from a Slide or all Comments from a SlideRange (version 1.5.0.0 2021-08-31) _PPT_CommentList: Get a list of all Comments in a Presentation (version 1.5.0.0 2021-08-31) _PPT_ConvertUnits: Convert units (like centimeters) to other units (like points) (version 1.3.0.0 2021-08-17) _PPT_HeaderFooterList: Returns a list of Headers and Footers for a Presentation (version 1.1.0.0 2021-07-25, removed with version 1.4.0.0 2021-08-25) _PPT_HeaderFooterSet: Sets the Header/Footer for a Slide/Slides or the Slide-/Notes-/Handout-/Title-Master of the Presentation (version 1.2.0.0 2021-08-09) _PPT_PresentationAttach: Attach to an already opened Presentation _PPT_PresentationClose: Close a Presentation _PPT_PresentationExport: Export one/multiple/all Slides as PDF or XPS. _PPT_PresentationExportGraphic: Export one/multiple/all Slides in a graphic format. _PPT_PresentationList: Returns a list of currently open Presentations (version 1.0.0.0 2021-07-20) _PPT_PresentationNew: Create a new Presentation _PPT_PresentationOpen: Open an existing Presentation _PPT_Print: Print one/multiple/all Slides of a Presentation (version 1.0.0.0 2021-07-20) _PPT_PresentationSave: Save a Presentation _PPT_PresentationSaveAs: Save a Presentation to another location or with another type _PPT_ShapeAdd: Add a Shape to a single or multiple Slides (version 1.1.0.0 2021-07-25) _PPT_ShapeAlignDistribute: Aligns and distributes the Shapes in the specified ShapeRange (version 1.6.0.0 - to be released) _PPT_ShapeCopyMove: Copy/move a Shape(s) of a single Slide to a Slide(s) in the same or a different Presentation (version 1.1.0.0 2021-07-25) _PPT_ShapeDelete: Delete a Shape or Shapes from a single or multiple Slides (version 1.1.0.0 2021-07-25) _PPT_SlideAdd: Add slide(s) to a Presentation _PPT_SlideCopyMove: Copy, move, duplicate Slide(s) _PPT_SlideDelete: Delete Slide(s) _PPT_SlideShow: Show a Presentation _PPT_TableGet: Extract data from a PowerPoint Table Shape to an array (version 1.3.0.0 2021-08-17) _PPT_TableSet: Write data to a PowerPoint Table Shape (version 1.3.0.0 2021-08-17) _PPT_TextFindReplace: Find & replace text throughout entire PowerPoint presentation (version 1.0.0.0 2021-07-20) _PPT_TextSet: Sets/modifies the Text of a Shape or Shapes of a single or multiple Slides (version 1.2.0.0 2021-08-09 Which functions do you want me to add to the UDF?
      ToDo list:
      create slide (JLogan3o13) - Done: _PPT_SlideAdd Apply template to slide (JLogan3o13) - Done: _PPT_SlideAdd Apply theme to slide (JLogan3o13) Cut/Copy/Duplicate/Move/Delete slide(s) (JLogan3o13) - Done: _PPT_SlideCopyMove, _PPT_SlideDelete Export slides (JLogan3o13) - Done: _PPT_PresentationExport Cut/Copy/Duplicate/Move/Delete shape(s) (JLogan3o13): Done : _PPT_ShapeCopyMove, _PPT_ShapeDelete (version 1.1.0.0 2021-07-25) ApplyAnimation, Select, SetDefaultProperties, and zOrder for shape(s) (JLogan3o13) Searching and replacing text (pcjunki) - Done: _PPT_TextFindReplace (version 1.0.0.0 2021-07-20) Export slides in a graphic format (JPG, GIF, PNG ...) (UEZ) - Done: _PPT_PresentationExportGraphic The UDF can be downloaded from the download forum.
       
    • By seadoggie01
      This UDF is because I'm tired of trying to use UI Automation and Send to automate Adobe Acrobat. I often need to read the contents of PDFs and Acrobat is not easy to work with as a window.  The functions are based on the API Reference from Adobe located here.
      Acrobat Pro is required for all functions.
      It's very beta right now, but it still seems to work. Currently, the functions are based around page level manipulation of PDF documents: re-arranging, swapping, deleting, and moving pages as this is what I use the most.
      Please feel free to request/suggest features!
       
       
    • By DonChunior
      Introduction 
      In the course of my research for a project involving, among other things, the transfer of large amounts of data, I came across the BITS service and from that the idea for this UDF was born.
      For a brief overview, I'll quote from Microsoft's BITS website (https://docs.microsoft.com/en-us/windows/win32/bits/background-intelligent-transfer-service-portal).
      Availability 🛒
      The BITS UDF can be downloaded from my GitHub repository:
      🔗 https://github.com/DonChunior/BITS-UDF
      Comments 💬
      Currently, only an alpha version of the UDF is available.
      This contains by and large the full functionality of the object interfaces, but still completely lacks error checking and handling.
      I will implement this in the upcoming beta version.
      Therefore I ask you to use the UDF only for testing purposes but not in productive code!
      Acknowledgment 🤝
      Many thanks to @Nine and @Danyfirex.
      You helped me very well in solving some tricky problems.
    • By Hermes
      I have Index.html where it contains a frame with a source "frame1.html". I can select/highlight elements in index.html but unable to select/highlight elements inside the frame with the src "frame1.html", the autoit output is throwing error:
      __WD_Post: URL=HTTP://127.0.0.1:9515/session/2143396006437be4005db3b84acc1496/element/8be1c3c4-5bb1-42b1-8cde-7954765cbc61/element; $sData={"using":"css selector","value":"frameset:nth-of-type(1)"} __WD_Post: StatusCode=404; ResponseText={"value":{"error":"no such element","message":"no such element: Unable to locate element: {\"method\... __WD_Post ==> No match: {"value":{"error":"no such element","message":"no such element: Unable to locate element: {\"method\":\"css selector\",\"selector\":\"frameset:nth-of-type(1)\"}\n (Session info: chrome=90.0.4430.212)","stacktrace":"Backtrace:\n\tOrdinal0 [0x00FCE7D3+124883]\n\tOrdinal0 [0x00FCE7B1+124849]\n\tGetHandleVerifier [0x01218688+193832]\n\tGetHandleVerifier [0x0123C478+340760]\n\tGetHandleVerifier [0x012361F1+315537]\n\tGetHandleVerifier [0x012516BA+427354]\n\tGetHandleVerifier [0x01236176+315414]\n\tGetHandleVerifier [0x0125174A+427498]\n\tGetHandleVerifier [0x0125D6EB+476555]\n\tGetHandleVerifier [0x0125154B+426987]\n\tGetHandleVerifier [0x01234FFD+310941]\n\tGetHandleVerifier [0x01235D8E+314414]\n\tGetHandleVerifier [0x01235D19+314297]\n\tGetHandleVerifier [0x012F31EC+1089676]\n\tGetHandleVerifier [0x012F17C9+1082985]\n\tGetHandleVerifier [0x012F13A3+1081923]\n\tGetHandleVerifier [0x013ED9FD+2115741]\n\tOrdinal0 [0x0111B82E+1488942]\n\tOrdinal0 [0x010B5A7D+1071741]\n\tOrdinal0 [0x010B559B+1070491]\n\tOrdinal0 [0x010B54B1+1070257]\n\tOrdinal0 [0x010EFF53+1310547]\n\tBaseThreadInitThunk [0x770662C4+36]\n\tRtlSubscribeWnfStateChangeNotification [0x776B1B69+1081]\n\tRtlSubscribeWnfStateChangeNotification [0x776B1B34+1028]\n"}} Auto IT Script:
      #Include "wd_core.au3" #Include "wd_helper.au3" Local $sDesiredCapabilities, $sSession SetupChrome() _WD_Startup() $sSession = _WD_CreateSession($sDesiredCapabilities) _WD_Navigate($sSession, 'index.html') _WD_LoadWait($sSession) Local $index = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, "frameset:nth-of-type(1)") Local $index1 = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, "frameset:nth-of-type(1)", $index) Local $index2 = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, "frame:nth-of-type(1)", $index1) Local $index3 = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, "frameset:nth-of-type(1)", $index2) _WD_HighlightElement($sSession, $index2, 1) _WD_HighlightElement($sSession, $index3, 1) _WD_Shutdown() Func SetupChrome() _WD_Option('Driver', 'chromedriver.exe') _WD_Option('Port', 9515) _WD_Option('DriverParams', '--log-path="' & @ScriptDir & '\chrome.log"') $sDesiredCapabilities = '{"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "args":["start-maximized","disable-infobars"]}}}}' EndFunc ;==>SetupChrome  

      frame1.html index.html
    • By Hermes
      Hi, sometimes when I run my script in GUI (SciTe Editor) or as an executable file, the chrome driver launches but the chrome browser does not but when I re-run the script again - chrome driver launches and so does the browser. Here is the error that I'm getting:
      __WD_Post: StatusCode=0; ResponseText=WinHTTP request timed out before Webdriver... __WD_Post ==> Send / Recv error: WinHTTP request timed out before Webdriver _WD_CreateSession: WinHTTP request timed out before Webdriver _WD_CreateSession ==> Webdriver Exception: HTTP status = 0 Just wondering if there's a way to re-launch both the driver and browser without having to rerun the script/executable.
       
       
×
×
  • Create New...