retval macro from ejecutar comando shell vba unix excel-vba vbscript

shell - macro - Llamar a Unix Script desde Excel Vba



vba comando shell (3)

Intento llamar a un conjunto de comandos de Unix desde VBA utilizando Plink (putty Command Line) pero los comandos no se están ejecutando. Voy a publicar el código de cualquier corrección o sugerencia sería útil.

Las ideas alternativas también son bienvenidas. Todo lo que tengo que hacer es acceder al permiso de cambio de archivo de Unix y mover los archivos a otras carpetas.

Pls encuentra el código a continuación

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


Hay un problema con la forma de abrir y escribir en el archivo:

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

Está comprobando el siguiente número de archivo disponible, almacenando el número como una variable "fNum" y luego abriendo un archivo como # 1, independientemente de lo que FreeFile () devolvió. Es posible que tenga un conflicto de número de archivo, por lo que puedo ver. Además, en mi extremo, el argumento "-s:" como línea de comando falla. Intente usar un archivo .cmd en su lugar, y llámelo como un comando:

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


Este método crea 2 archivos. Uno (chg.bat) que invoca a Plink y se registra en el servidor. Además, instruye a Plink para que ejecute los comandos en el segundo archivo (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


Una opción sería abrir la sesión plink en WScript.Shell lugar de ejecutarla con un archivo de script utilizando el Shell de VBA. El programa plink se ejecutará en modo interactivo desde la línea de comandos, y el objeto WshExec le brinda acceso directo a la entrada estándar y flujos de salida estándar del proceso que está ejecutando. Este breve ejemplo demuestra su uso de forma interactiva (se conecta al servidor telnet público de telehack.com y ejecuta el comando fnord ) con toda la salida de la consola que se copia en la ventana inmediata:

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

En su caso, no hay mucha "interacción" con el servidor al que se está conectando, por lo que puede ser tan fácil como enviar todos sus comandos directamente a StdIn . Dada la amplia gama de compatibilidad de protocolos que posee plink , me sorprendería que ejecutar el archivo de script sea sustancialmente diferente de esto:

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

Si eso se ejecuta demasiado rápido, siempre puede probar para asegurarse de que está obteniendo las respuestas apropiadas del servidor o agregar una corta espera entre el envío de comandos a StdIn .