Putty automation using excel vba

josechakkala

New Member
Joined
Nov 23, 2013
Messages
22
Hi,

Some one please guide me how to automate putty using vba. I am able to invoke putty.exe using Shell command, but not able to enter the user name and password. Tried Sendkeys for entering username, but that is not working.

PuttyWindow = Shell("D:\putty.exe -telnet servername", vbNormalFocus)
AppActivate PuttyWindow, True

Application.Wait (Now + TimeValue("0:00:02"))

SendKeys "username", True
SendKeys "{ENTER}", True


Thanks in Advance
Jose
 
Here is the full code.
Dim PuttyWindow
PuttyWindow = Shell("C:\Program Files\Microsoft Application Virtualization Client\sfttray.exe /launch PuTTY username @server ", vbNormalFocus)
AppActivate PuttyWindow, True
Application.Wait (Now + TimeValue("0:00:05"))
SendKeys "Password"
SendKeys "{ENTER}"
 
Upvote 0

Excel Facts

Excel Joke
Why can't spreadsheets drive cars? They crash too often!
Getting type mismacth error in this code...using in office 2016 , 64 bit
getting error for tempHwnd


VBA Code:
Option Explicit

Private Const ConsoleClassName As String = "ConsoleWindowClass"
Private Const PuTTYClassName As String = "PuTTY"

Private Const WM_CHAR As Long = &H102
Private Const WM_KEYDOWN As Long = &H100
Private Const GW_HWNDNEXT = 2

'https://msdn.microsoft.com/en-us/library/office/gg264421.aspx
'64-Bit Visual Basic for Applications Overview

#If VBA7 Then
    'New VBA version 7 compiler, therefore >= Office 2010
    'PtrSafe means function works in 32-bit and 64-bit Office
    'LongPtr type alias resolves to Long (32 bits) in 32-bit Office, or LongLong (64 bits) in 64-bit Office
    
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
        
    Private Declare PtrSafe Function GetParent Lib "user32" _
        (ByVal hwnd As LongPtr) As LongPtr
        
    Private Declare PtrSafe Function GetWindow Lib "user32" _
        (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr
            
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" _
        (ByVal hwnd As LongPtr, lpdwProcessId As LongPtr) As Long
        
    Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" _
        (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
        
#Else
    'Old VBA version 6 or earlier compiler, therefore <= Office 2007
    
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
        
    Private Declare Function GetParent Lib "user32" _
        (ByVal hwnd As Long) As Long
        
    Private Declare Function GetWindow Lib "user32" _
        (ByVal hwnd As Long, ByVal wCmd As Long) As Long
            
    Private Declare Function GetWindowThreadProcessId Lib "user32" _
        (ByVal hwnd As Long, lpdwProcessId As Long) As Long
        
    Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
        (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        
#End If


#If VBA7 Then
Public Sub SendChars(hwnd As LongPtr, sChars As String)
#Else
Public Sub SendChars(hwnd As Long, sChars As String)
#End If
    Dim i As Long
    Dim ret As Long
    
    For i = 1 To Len(sChars)
        ret = PostMessage(hwnd, WM_CHAR, Asc(Mid(sChars, i, 1)), 0&)
        'ret = PostMessage(hWnd, WM_KEYDOWN, Asc(Mid(sChars, i, 1)), 0&)
    Next
End Sub

#If VBA7 Then
Public Function GetWindowHandle(hInstance As Long) As Long
#Else
Public Function GetWindowHandle(hInstance As Long) As Long
#End If

#If VBA7 Then
    Dim tempHwnd As LongPtr
#Else
    Dim tempHwnd As Long
#End If

    ' Grab the first window handle that Windows finds:
    tempHwnd = FindWindow(vbNullString, vbNullString)
    
    ' Loop until you find a match or there are no more window handles:
    Do Until tempHwnd = 0
        ' Check if no parent for this window
        If GetParent(tempHwnd) = 0 Then
            ' Check for PID match
            If hInstance = ProcIDFromWnd(tempHwnd) Then
                ' Return found handle
                GetWindowHandle = tempHwnd
                ' Exit search loop
                Exit Do
            End If
        End If
        
        ' Get the next window handle
        tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)
    Loop
End Function

#If VBA7 Then
Private Function ProcIDFromWnd(ByVal hwnd As LongPtr) As Long
#Else
Private Function ProcIDFromWnd(ByVal hwnd As Long) As Long
#End If
    Dim idProc As Long
    
    ' Get PID for this HWnd
    GetWindowThreadProcessId hwnd, idProc
    
    ' Return PID
    ProcIDFromWnd = idProc
End Function
 
Upvote 0
This:

VBA Code:
#If VBA7 Then
Public Function GetWindowHandle(hInstance As Long) As Long
#Else
Public Function GetWindowHandle(hInstance As Long) As Long
#End If

needs to be this:

VBA Code:
#If VBA7 Then
Public Function GetWindowHandle(hInstance As LongPtr) As LongPtr
#Else
Public Function GetWindowHandle(hInstance As Long) As Long
#End If
 
Upvote 0
But now getting ByRef argument type mismatch for idProc
VBA Code:
Option Explicit

Private Const ConsoleClassName As String = "ConsoleWindowClass"
Private Const PuTTYClassName As String = "PuTTY"

Private Const WM_CHAR As Long = &H102
Private Const WM_KEYDOWN As Long = &H100
Private Const GW_HWNDNEXT = 2

'https://msdn.microsoft.com/en-us/library/office/gg264421.aspx
'64-Bit Visual Basic for Applications Overview

#If VBA7 Then
    'New VBA version 7 compiler, therefore >= Office 2010
    'PtrSafe means function works in 32-bit and 64-bit Office
    'LongPtr type alias resolves to Long (32 bits) in 32-bit Office, or LongLong (64 bits) in 64-bit Office
   
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
       
    Private Declare PtrSafe Function GetParent Lib "user32" _
        (ByVal hwnd As LongPtr) As LongPtr
       
    Private Declare PtrSafe Function GetWindow Lib "user32" _
        (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr
           
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" _
        (ByVal hwnd As LongPtr, lpdwProcessId As LongPtr) As Long
       
    Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" _
        (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
       
#Else
    'Old VBA version 6 or earlier compiler, therefore <= Office 2007
   
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
       
    Private Declare Function GetParent Lib "user32" _
        (ByVal hwnd As Long) As Long
       
    Private Declare Function GetWindow Lib "user32" _
        (ByVal hwnd As Long, ByVal wCmd As Long) As Long
           
    Private Declare Function GetWindowThreadProcessId Lib "user32" _
        (ByVal hwnd As Long, lpdwProcessId As Long) As Long
       
    Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
        (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
       
#End If


#If VBA7 Then
Public Sub SendChars(hwnd As LongPtr, sChars As String)
#Else
Public Sub SendChars(hwnd As Long, sChars As String)
#End If
    Dim i As Long
    Dim ret As Long
   
    For i = 1 To Len(sChars)
        ret = PostMessage(hwnd, WM_CHAR, Asc(Mid(sChars, i, 1)), 0&)
        'ret = PostMessage(hWnd, WM_KEYDOWN, Asc(Mid(sChars, i, 1)), 0&)
    Next
End Sub

#If VBA7 Then
Public Function GetWindowHandle(hInstance As Long) As LongPtr
#Else
Public Function GetWindowHandle(hInstance As Long) As Long
#End If

#If VBA7 Then
    Dim tempHwnd As LongPtr
#Else
    Dim tempHwnd As Long
#End If

    ' Grab the first window handle that Windows finds:
    tempHwnd = FindWindow(vbNullString, vbNullString)
   
    ' Loop until you find a match or there are no more window handles:
    Do Until tempHwnd = 0
        ' Check if no parent for this window
        If GetParent(tempHwnd) = 0 Then
            ' Check for PID match
            If hInstance = ProcIDFromWnd(tempHwnd) Then
                ' Return found handle
                GetWindowHandle = tempHwnd
                ' Exit search loop
                Exit Do
            End If
        End If
       
        ' Get the next window handle
        tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)
    Loop
End Function

#If VBA7 Then
Private Function ProcIDFromWnd(ByVal hwnd As LongPtr) As LongPtr
#Else
Private Function ProcIDFromWnd(ByVal hwnd As Long) As Long
#End If
    Dim idProc As Long
   
    ' Get PID for this HWnd
    GetWindowThreadProcessId hwnd, idProc
   
    ' Return PID
    ProcIDFromWnd = idProc
End Function
 
Upvote 0
Issue resolved after correcting
Dim idProc As LongPtr

VBA Code:
#End If
    Dim idProc As LongPtr
   
    ' Get PID for this HWnd
    GetWindowThreadProcessId hwnd, idProc
 
Upvote 0
VBA Code:
#If VBA7 Then
Public Function GetWindowHandle(hInstance As Long) As LongPtr
#Else
Public Function GetWindowHandle(hInstance As Long) As Long
#End If
I think the above is correct, however I used a confusing name for hInstance, because it's actually a process id (always a Long), not a handle of any kind.

The error is in ProcIDFromWnd, where a pointer to idProc should be passed by value to GetWindowThreadProcessId, as shown here:
VBA Code:
#If VBA7 Then
Private Function ProcIDFromWnd(ByVal hwnd As LongPtr) As Long
#Else
Private Function ProcIDFromWnd(ByVal hwnd As Long) As Long
#End If
    Dim idProc As Long

    ' Get PID for this HWnd
    GetWindowThreadProcessId hwnd, VarPtr(idProc)
  
    ' Return PID
    ProcIDFromWnd = idProc
End Function

Based on post #11, Putty automation using excel vba, here is the complete code with the corrections.

Test routine in a standard module (eg. Module1):
VBA Code:
Option Explicit

Public Sub test()

    Dim PuttyPID As Double
    #If VBA7 Then
    Dim PuttyHwnd As LongPtr
    #Else
    Dim PuttyHwnd As Long
    #End If
    Dim serverName As String, username As String, password As String
 
    serverName = "xxx.yyy"
    username = "xxxx"
    password = "xxxx"
 
    PuttyPID = Shell("C:\Program Files\PuTTY\putty.exe -telnet  " & serverName, vbNormalFocus)   'CHANGE PATH TO .EXE
 
    'Get window handle of the PuTTY Telnet command window

    PuttyHwnd = GetWindowHandle(CLng(PuttyPID))
 
    If PuttyHwnd <> 0 Then
     
        SendChars PuttyHwnd, username & vbCr
        Application.Wait DateAdd("s", 1, Now)
 
        SendChars PuttyHwnd, password & vbCr
        Application.Wait DateAdd("s", 1, Now)
 
        SendChars PuttyHwnd, "DIR" & vbCr  'DIR command
 
    End If
 
End Sub
API declarations and supporting functions in a standard module (e.g. Module2):
VBA Code:
Option Explicit

Private Const ConsoleClassName As String = "ConsoleWindowClass"
Private Const PuTTYClassName As String = "PuTTY"

Private Const WM_CHAR As Long = &H102
Private Const WM_KEYDOWN As Long = &H100
Private Const GW_HWNDNEXT = 2

'https://msdn.microsoft.com/en-us/library/office/gg264421.aspx
'64-Bit Visual Basic for Applications Overview

#If VBA7 Then
    'New VBA version 7 compiler, therefore >= Office 2010
    'PtrSafe means function works in 32-bit and 64-bit Office
    'LongPtr type alias resolves to Long (32 bits) in 32-bit Office, or LongLong (64 bits) in 64-bit Office
  
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
      
    Private Declare PtrSafe Function GetParent Lib "user32" _
        (ByVal hwnd As LongPtr) As LongPtr
      
    Private Declare PtrSafe Function GetWindow Lib "user32" _
        (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr
          
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" _
        (ByVal hwnd As LongPtr, ByVal lpdwProcessId As LongPtr) As Long
  
    Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
        (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As LongPtr) As Long
  
    Private Declare PtrSafe Sub Sleep Lib "kernel32" _
        (ByVal dwMilliseconds As Long)
  
    Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" _
        (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
      
#Else
    'Old VBA version 6 or earlier compiler, therefore <= Office 2007
  
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
      
    Private Declare Function GetParent Lib "user32" _
        (ByVal hwnd As Long) As Long
      
    Private Declare Function GetWindow Lib "user32" _
        (ByVal hwnd As Long, ByVal wCmd As Long) As Long
          
    Private Declare Function GetWindowThreadProcessId Lib "user32" _
        (ByVal hwnd As Long, ByVal lpdwProcessId As Long) As Long
  
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
        (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
      
    Private Declare Sub Sleep Lib "kernel32" _
        (ByVal dwMilliseconds As Long)
  
    Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
        (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
      
#End If


#If VBA7 Then
Public Sub SendChars(hwnd As LongPtr, sChars As String)
#Else
Public Sub SendChars(hwnd As Long, sChars As String)
#End If
    Dim i As Long
    Dim ret As Long
  
    For i = 1 To Len(sChars)
        ret = PostMessage(hwnd, WM_CHAR, Asc(Mid(sChars, i, 1)), 0&)
        'ret = PostMessage(hWnd, WM_KEYDOWN, Asc(Mid(sChars, i, 1)), 0&)
    Next
End Sub


'Original code with argument name changed from hInstance to pid and without debugging to get window title
#If VBA7 Then
Public Function GetWindowHandle(pid As Long) As LongPtr
#Else
Public Function GetWindowHandle(pid As Long) As Long
#End If

#If VBA7 Then
    Dim tempHwnd As LongPtr
#Else
    Dim tempHwnd As Long
#End If
    Dim strWindowTitle As String

    ' Grab the first window handle that Windows finds:
    tempHwnd = FindWindow(vbNullString, vbNullString)
  
    ' Loop until you find a match or there are no more window handles:
    Do Until tempHwnd = 0
        ' Check if no parent for this window
        If GetParent(tempHwnd) = 0 Then
            ' Check for PID match
            If pid = ProcIDFromWnd(tempHwnd) Then
                ' Return found handle
                GetWindowHandle = tempHwnd
                ' Exit search loop
                Exit Do
            End If
        End If
      
        ' Get the next window handle
        tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)
    Loop
End Function


#If VBA7 Then
Private Function ProcIDFromWnd(ByVal hwnd As LongPtr) As Long
#Else
Private Function ProcIDFromWnd(ByVal hwnd As Long) As Long
#End If
    Dim idProc As Long

    ' Get PID for this HWnd
    GetWindowThreadProcessId hwnd, VarPtr(idProc)
  
    ' Return PID
    ProcIDFromWnd = idProc
End Function
 
Last edited:
Upvote 0

Forum statistics

Threads
1,223,275
Messages
6,171,126
Members
452,381
Latest member
Nova88

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top