6

Im trying to call a set of Unix commands from VBA using Plink ( putty Command Line) but the commands are not getting Executed . I ll post the code any corrections or suggestions would be helpful.

alternative Ideas are also Welcomed , All i have to do is Access unix file change access permission and move the files to other folders.

Pls find the code below

Public Sub Chgaccper()

Dim vPath As String
Dim vFile As String
Dim vSubpath As String
Dim vscript As String
Dim fNum As Long
Dim oShell

Set fso = CreateObject("scripting.filesystemobject")

vPath = ThisWorkbook.Path

'Mounting file command for ftp.exe
fNum = FreeFile()
Open vPath & "\Chg.txt" For Output As #1
Print #1, "c:\"
Print #1, "set PATH=" & vPath & ";%PATH% "
Print #1, " "
Print #1, "plink server Name -l uname -pw Password "
Print #1, " "
Print #1, "cd /root/home/temp "
Print #1, " "
Print #1, "chmod 666 *.csv "
Print #1, " "
Print #1, "cd /root/home/temp1 "
Print #1, " "
Print #1, "chmod 666 *.csv "
Print #1, " "
Print #1, "exit "
Print #1, " "
Close #1

vscript = "" & vPath & "\Chg.txt"

If fso.FolderExists("C:\Windows\System32") = False Then
Shell "C:\WINNT\system32\cmd.exe -s:" & vscript & ""
Else
Shell "C:\WINDOWS\system32\cmd.exe -s:" & vscript & ""

End If

SetAttr vPath & "\Chg.txt", vbNormal
Kill vPath & "\Chg.txt"


End Sub
1
  • What is the result of your code? Do you have a Chg.txt, can you show the content of it? What happens when you try yo execute the script directly? Commented Jan 4, 2017 at 13:40

3 Answers 3

8
+200

One option would be to open the plink session in a WScript.Shell instead of executing it with a script file using VBA's Shell. The plink program will run in interactive mode from the command line, and the WshExec object gives you direct access to the standard input and standard output streams of the process that you're executing. This short example demonstrates using it interactively (it logs onto the public telehack.com telnet server and executes the fnord command) with all of the console output being copied into the immediate window:

Private Sub Fnord()
    Dim shell As Object
    Set shell = CreateObject("WScript.Shell")
    Dim console As Object
    'Open plink in interactive mode.
    Set console = shell.Exec("c:\putty\plink -telnet telehack.com -P 443")
    'Wait for a command prompt.
    WaitForResponseText console, "."
    'Send the fnord command to standard input.
    console.StdIn.Write ("fnord" & vbCr)
    'Wait for the server to echo it back.
    WaitForResponseText console, ".fnord"
    'Read the standard output through the next command prompt.
    WaitForResponseText console, "."
    'Exit the telent session.
    console.StdIn.Write ("exit" & vbCr)
End Sub

Private Sub WaitForResponseText(console As Object, response As String)
    Dim out As String
    'Make sure there's output to read.
    If console.StdOut.AtEndOfStream Then Exit Sub
    Do
        'Read a line from standard output.
        out = console.StdOut.ReadLine()
        'Not strictly required, but allows killing the process if this doesn't exit.
        DoEvents
        'Send the server output to the immediate window.
        Debug.Print out
        'Check for the response we're waiting for.
        If InStr(out, response) Then
            Exit Do
        End If
    Loop Until console.StdOut.AtEndOfStream
End Sub

In your case, there isn't much "interaction" going on with the server you're connecting to, so it may be as easy as just sending all of your commands directly to StdIn. Given the wide range of protocol support that plink has, I'd be surprised if running the script file is substantially different that this:

Public Sub Chgaccper()
    Dim shell As Object
    Set shell = CreateObject("WScript.Shell")
    Dim console As Object
    'Open plink in interactive mode.
    Set console = shell.Exec("c:\putty\plink server Name -l uname -pw Password")
    'Send your commands to the standard input.
    console.StdIn.Write ("cd /root/home/temp" & vbCr)
    console.StdIn.Write ("chmod 666 *.csv" & vbCr)
    console.StdIn.Write ("cd /root/home/temp1" & vbCr)
    console.StdIn.Write ("chmod 666 *.csv" & vbCr)
    console.StdIn.Write ("exit" & vbCr)
End Sub

If that runs too fast, you can always test to make sure you're getting appropriate server responses or add a short wait between sending commands to StdIn.

Sign up to request clarification or add additional context in comments.

Comments

5

There's a problem with how you open and write to the file:

fNum = FreeFile()
Open vPath & "\Chg.txt" For Output As #1
Print #1, "c:\"

You're checking the next available file number, storing the number as a variable "fNum" and then opening a file as #1, regardless of what FreeFile() returned. You might have a file number conflict, as far as I can see. Also, on my end the "-s:" as command line argument fails. Try using a .cmd file instead, and call it as a command:

Public Sub Chgaccper()

Dim vPath As String
Dim vFile As String
Dim vSubpath As String
Dim vscript As String
Dim fNum As Long
Dim oShell

Set fso = CreateObject("scripting.filesystemobject")

vPath = ThisWorkbook.Path

'Mounting file command for ftp.exe
fNum = FreeFile()
Open vPath & "\Chg.cmd" For Output As fNum
Print #fNum, "c:\"
Print #fNum, "set PATH=" & vPath & ";%PATH% "
Print #fNum, " "

Print #fNum, "plink server Name -l uname -pw Password "
Print #fNum, " "
Print #fNum, "cd /root/home/temp "
Print #fNum, " "
Print #fNum, "chmod 666 *.csv "
Print #fNum, " "
Print #fNum, "cd /root/home/temp1 "
Print #fNum, " "
Print #fNum, "chmod 666 *.csv "
Print #fNum, " "
Print #fNum, "exit "
Close #fNum

vscript = "" & vPath & "\Chg.cmd"

If fso.FolderExists("C:\Windows\System32") = False Then
    Shell "C:\WINNT\system32\cmd.exe /k " & vscript & ""
Else
    Shell "C:\WINDOWS\system32\cmd.exe /k " & vscript & ""
End If


SetAttr vPath & "\Chg.cmd", vbNormal
Kill vPath & "\Chg.cmd"

End Sub

Ref: https://msdn.microsoft.com/en-us/library/office/gg264526.aspx

Comments

1

This method creates 2 files. One (chg.bat) which invokes Plink and logs into the server. Additionally it instructs Plink to execute the commands in the 2nd file (commands.txt).

Public Sub Chgaccper()

    Dim vPath As String
    Dim vscript As String

    vPath = ThisWorkbook.Path

    Open vPath & "\Chg.bat" For Output As #1
    Print #1, "c:\"
    Print #1, "set PATH=" & vPath & ";%PATH% "
    Print #1, "plink ServerName -l uname -pw Password -m commands.txt"
    Close #1
    Open vPath & "\commands.txt" For Output As #2
    Print #2, "cd /root/home/temp"
    Print #2, "chmod 666 *.csv"
    Print #2, "cd /root/home/temp1"
    Print #2, "chmod 666 *.csv"
    Print #2, "exit"
    Close #2

    vscript = "" & vPath & "\Chg.bat"

    Shell vscript

    SetAttr vPath & "\Chg.bat", vbNormal
    SetAttr vPath & "\commands.txt", vbNormal
    Kill vPath & "\Chg.bat"
    Kill vPath & "\commands.txt"

End Sub

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.