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
.