Hola a todos. Estoy intentando correr el cmd a través de un formulario pero no puedo realizar lo de comandos multiples.
If My.Computer.FileSystem.FileExists(midirectorio & "\runpkr00.exe") Then
Dim archivo = My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.t01")
For Each file As String In archivo
'Dim archivo = My.Computer.FileSystem.GetFileInfo(File)
Dim comando As String
Dim cmdir As String
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d " & file & ".t01"
Shell("cmd.exe /k" + cmdir + comando)
next
end if
como resultado me da:
El nombre de archivo, el nombre de directorio o la sintaxis de la etiqueta del volumen no son correctos.
C:\Users\rchaconr\Documents\Visual Studio 2013\Projects\CONVERSOR DATOS GPS\CONV
ERSOR DATOS GPS\bin\Debug>
y lo que deseo es que se ejecute
> cd midirectorio
c:\midirectorio>runpkr00.exe -d archivo.t01
Espero que me puedan entender y tener un poco de su ayuda. Muchas gracias
Los nombres de los archivos que te devuelve las función que los lista te da la ruta completa del archivo, no solamente el nombre. Puede ser que tu error está ahí. Para resolverlo elimina el directorio raíz del nombre del archivo.
Cita de: El Benjo en 12 Junio 2014, 19:02 PM
Los nombres de los archivos que te devuelve las función que los lista te da la ruta completa del archivo, no solamente el nombre. Puede ser que tu error está ahí. Para resolverlo elimina el directorio raíz del nombre del archivo.
si coloco
Shell("cmd.exe /k" & cmdir)
ejecuta normal, pero hasta ahí noma. Lo que quiero es que además de ejecutar ese comando también se ejecute el otro en la misma consola.
Ah, ok, ya te entendí. :P
Para eso debes poner:
Shell("cmd.exe /k" + cmdir + " & " + comando)
El símbolo "&" hasta donde yo sé, se utiliza para separar comandos en la consola de windows. Dinos si te funciona.
Cita de: El Benjo en 12 Junio 2014, 19:43 PM
Ah, ok, ya te entendí. :P
Para eso debes poner:
Shell("cmd.exe /k" + cmdir + " & " + comando)
El símbolo "&" hasta donde yo sé, se utiliza para separar comandos en la consola de windows. Dinos si te funciona.
Si me corre pero solo me ejecuta el comando "cmdir" mas no el de "comando". ¿Que puede estar mal?
En si todo el codigo que tengo para el comand es:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim midirectorio As String = TextBox1.Text
If midirectorio = "" Then
MessageBox.Show("Debe seleccionar la ruta donde se encuentra la data", "Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error)
Else
Try
My.Computer.FileSystem.CopyFile(
"C:\Program Files\convert data\runpkr00.exe",
midirectorio & "\runpkr00.exe",
Microsoft.VisualBasic.FileIO.UIOption.AllDialogs,
Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)
Catch ex As Exception
MsgBox(ex.Message.ToString, MsgBoxStyle.Critical)
End Try
End If
If My.Computer.FileSystem.FileExists(midirectorio & "\runpkr00.exe") Then
For Each archivo In My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.t01")
Dim comando As String
Dim cmdir As String
Dim nombre As String
nombre = My.Computer.FileSystem.GetName(archivo)
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d " & nombre & ".t01"
Shell("cmd.exe /k" + cmdir + " & " + comando)
Next
End If
End Sub
Mmmmmm, no sé en qué esté fallando, pero lo más seguro es que sea en la forma en que se construye la cadena.
Intenta poniendo un punto de interrupción y copia toda la cadena como debería salir al final. Luego escribe esa cadena en una consola de comandos y ve si también te da error. si es así entonces no es problema de programación sino de la construcción de la cadena.
no te sirve mas crear una tubería (pipe) como el ejemplo de esta pagina?
http://www.vbforums.com/showthread.php?381405-Automate-Command-Prompt-Window-(CMD)-Redirect-Output-to-Application-2003-2005 (http://www.vbforums.com/showthread.php?381405-Automate-Command-Prompt-Window-(CMD)-Redirect-Output-to-Application-2003-2005)
Lex, no conocía la existencia de los métodos para redirigir la salida y la entrada de las aplicaciones.
Rochro, el método que menciona Lex te permite enviar los comandos uno a uno sin necesidad de abrir múltiples ventanas. Esta sería una opción mejor.
Cita de: El Benjo en 13 Junio 2014, 21:32 PM
Lex, no conocía la existencia de los métodos para redirigir la salida y la entrada de las aplicaciones.
Rochro, el método que menciona Lex te permite enviar los comandos uno a uno sin necesidad de abrir múltiples ventanas. Esta sería una opción mejor.
Chicos! Muchas gracias, ya lo adapté pero hay algo que no me sale que es que si tengo en mi directorio mas de un archivo sólo lo aplica con uno y no con todos los que están en ese directorio.
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim midirectorio As String = TextBox1.Text
If midirectorio = "" Then
MessageBox.Show("Debe seleccionar la ruta donde se encuentra la data", "Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error)
Else
Try
My.Computer.FileSystem.CopyFile(
"C:\Program Files\convert data\runpkr00.exe",
midirectorio & "\runpkr00.exe",
Microsoft.VisualBasic.FileIO.UIOption.AllDialogs,
Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)
Catch ex As Exception
MsgBox(ex.Message.ToString, MsgBoxStyle.Critical)
End Try
End If
If My.Computer.FileSystem.FileExists(midirectorio & "\runpkr00.exe") Then
Dim CMDThread As New Threading.Thread(AddressOf CMDAutomate)
CMDThread.Start()
End If
End Sub
Private Sub CMDAutomate()
Dim midirectorio As String = TextBox1.Text
Dim myprocess As New Process
Dim StartInfo As New System.Diagnostics.ProcessStartInfo
StartInfo.FileName = "cmd"
StartInfo.RedirectStandardInput = True
StartInfo.RedirectStandardOutput = True
StartInfo.UseShellExecute = False
StartInfo.CreateNoWindow = True
myprocess.StartInfo = StartInfo
myprocess.Start()
For Each archivo As String In My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.t01")
Dim SR As System.IO.StreamReader = myprocess.StandardOutput
Dim SW As System.IO.StreamWriter = myprocess.StandardInput
Dim comando As String
Dim cmdir As String
Dim nombre As String
nombre = My.Computer.FileSystem.GetName(archivo)
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d " & nombre
SW.WriteLine(cmdir)
SW.WriteLine(comando)
Results = SR.ReadToEnd
SW.Close()
SR.Close()
Invoke(Finished)
Next
End Sub
No estoy seguro pero creo que tu problema puede estar en:
Invoke(Finished)
Si lo que quieres es que el método se invoke con cada archivo entonces está bien. Pero si lo que quieres es que se invoque al final de todo el procedimiento entonces deberías ponerlo después del "next".
Tampoco creo que haya necesidad de cerrar los streams en cada iteración por lo tanto también deberías provar dejando el código como sigue:
Dim SR As System.IO.StreamReader = myprocess.StandardOutput
Dim SW As System.IO.StreamWriter = myprocess.StandardInput
Dim comando As String
Dim cmdir As String
Dim nombre As String
For Each archivo As String In My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.t01")
nombre = My.Computer.FileSystem.GetName(archivo)
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d " & nombre
SW.WriteLine(cmdir)
SW.WriteLine(comando)
Results = SR.ReadToEnd
Invoke(Finished)
Next
SW.Close()
SR.Close()
End Sub
Para dejar más limpio el bucle.
Cita de: El Benjo en 18 Junio 2014, 06:26 AM
No estoy seguro pero creo que tu problema puede estar en:
Invoke(Finished)
Benjo, hice lo que me dijiste y sigue igual.
Estás seguro de que no se ejecuta "runpkr00.exe -d " & nombre por cada archivo? O sólo no te muestra la información en la pantalla?
Para qué es la línea "Invoke(Finished)"?
Has colocado puntos de interrupción en el bucle para comprobar que realmente hace cada iteración que debería?
Si la respuesta a la pregunta anterior es "sí", ¿se ejecuta cada iteración sin problemas o da algún error?
Cita de: El Benjo en 18 Junio 2014, 20:25 PM
Estás seguro de que no se ejecuta "runpkr00.exe -d " & nombre por cada archivo? O sólo no te muestra la información en la pantalla?
Para qué es la línea "Invoke(Finished)"?
Has colocado puntos de interrupción en el bucle para comprobar que realmente hace cada iteración que debería?
Si la respuesta a la pregunta anterior es "sí", ¿se ejecuta cada iteración sin problemas o da algún error?
Se ejecuta todo bien pero no en todos los archivos que se encuentran en el directorio, o sea no me funciona el bucle.
ejem:
directorio
archivo1.t01 ---- solo ejecuta en el primer archivo
archivo2.t01
archivo3.t01
archivo4.t01
El invoke(Finished) es para que me imprima el resultado de la aplicación de los comandos.
Modifica el código como sigue:
Try
For Each archivo As String In My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.t01")
nombre = My.Computer.FileSystem.GetName(archivo)
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d " & nombre
SW.WriteLine(cmdir)
SW.WriteLine(comando)
Results = SR.ReadToEnd
Invoke(Finished)
Catch e As Exception
End Try
Next
SW.Close()
SR.Close()
End Sub
Coloca un punto de interrupción en la línea del catch y fíjate en el error que arroja. Si no arroja ningún error no te queda de otra que colocar el punto de interrupción en la primera línea del bucle e ir ejecutando línea por línea para ver el error.
Cita de: El Benjo en 18 Junio 2014, 23:12 PM
Coloca un punto de interrupción en la línea del catch y fíjate en el error que arroja. Si no arroja ningún error no te queda de otra que colocar el punto de interrupción en la primera línea del bucle e ir ejecutando línea por línea para ver el error.
Benjo, realicé el paso a paso para ver el error y al parecer no termina el for porque llega hasta el punto
Results = SR.ReadToEnd
y de ahi termina o sea no finaliza el for .
Eso significa que se produce el error en esa línea. Me imagino que la función es creada en un hilo independiente del hilo principal, por eso es que no te salta error sólo sale del bucle y de la función... Y YA!
Para comprobar qué tipo de error es coloca el for dentro del tray/catch y coloca el punto de interrupción en la línea correspondiente al cath (como te indiqué en el código anterior) en la variable "e" estará la información correspondiente al error. Dinos cuál es para ver cómo se puede solucionar.
Cita de: El Benjo en 19 Junio 2014, 00:11 AM
Eso significa que se produce el error en esa línea. Me imagino que la función es creada en un hilo independiente del hilo principal, por eso es que no te salta error sólo sale del bucle y de la función... Y YA!
Para comprobar qué tipo de error es coloca el for dentro del tray/catch y coloca el punto de interrupción en la línea correspondiente al cath (como te indiqué en el código anterior) en la variable "e" estará la información correspondiente al error. Dinos cuál es para ver cómo se puede solucionar.
En Results me bota
Nothing y como te digo se queda en results y termina. No llega a la parte del Catch.
Try
For Each file As String In My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.T01")
nombre = My.Computer.FileSystem.GetName(file)
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d -s " & nombre
SW.WriteLine(cmdir)
SW.WriteLine(comando)
Results = SR.ReadToEnd
'SW.Close()
'SR.Close()
Invoke(Finished)
Next
Catch e As Exception
End Try
SW.Close()
SR.Close()
Ok, intenta llamar a la función dentro del mismo hilo para que la aplicación te bote el error y "a la fuerza" se detenga la ejecución. De esta manera podrás ver por qué la segunda vez que se ejecuta "Results = SR.ReadToEnd" No te funciona.
Estoy viendo otra cosa: No veo en ninguna parte del código que declares la variable Results. Puedes por favor poner cómo la declaras, creo que el error puede estar ahí.
Cita de: El Benjo en 19 Junio 2014, 05:41 AM
Ok, intenta llamar a la función dentro del mismo hilo para que la aplicación te bote el error y "a la fuerza" se detenga la ejecución. De esta manera podrás ver por qué la segunda vez que se ejecuta "Results = SR.ReadToEnd" No te funciona.
Estoy viendo otra cosa: No veo en ninguna parte del código que declares la variable Results. Puedes por favor poner cómo la declaras, creo que el error puede estar ahí.
Aquí te paso todo el código de mi aplicación pero ahora tengo otro problema y es que al momento de quitarle todos los puntos de interrupción ya no me ejecuta, se queda en
My.Computer.FileSystem.CopyFile .
Cuando le quito el código
'Results = SR.ReadToEnd
'SW.Close()
'SR.Close()
'Invoke(Finished)
y coloco el punto de interrupción en el for each me corre todo, algo debe de pasar con eso.
Imports System
Imports System.IO
Imports System.IO.StreamWriter
Public Class Form1
Inherits System.Windows.Forms.Form
Private Results As String
Private Delegate Sub delUpdate()
Private Finished As New delUpdate(AddressOf UpdateText)
Private Sub btnexaminar_Click(sender As Object, e As EventArgs) Handles btnexaminar.Click
Dim Dir As New FolderBrowserDialog
If Dir.ShowDialog = Windows.Forms.DialogResult.OK Then
TextBox1.Text = Dir.SelectedPath
End If
End Sub
Private Sub btndat_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btndat.Click
Dim midirectorio As String = TextBox1.Text
Dim CMDThread As New Threading.Thread(AddressOf CMDAutomate)
If midirectorio = "" Then
MessageBox.Show("Debe seleccionar la ruta donde se encuentra la data", "Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error)
Else
My.Computer.FileSystem.CopyFile("C:\Program Files\convert data\runpkr00.exe", midirectorio & "\runpkr00.exe", Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing)
End If
CMDThread.Start()
End Sub
Private Sub CMDAutomate()
Dim midirectorio As String = TextBox1.Text
Dim myprocess As New Process
Dim StartInfo As New System.Diagnostics.ProcessStartInfo
StartInfo.FileName = "cmd"
StartInfo.RedirectStandardInput = True
StartInfo.RedirectStandardOutput = True
StartInfo.UseShellExecute = False
StartInfo.CreateNoWindow = True
myprocess.StartInfo = StartInfo
myprocess.Start()
Dim SR As System.IO.StreamReader = myprocess.StandardOutput
Dim SW As System.IO.StreamWriter = myprocess.StandardInput
Dim comando As String
Dim cmdir As String
Dim nombre As String
For Each file As String In My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.T01")
nombre = My.Computer.FileSystem.GetName(file)
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d -s " & nombre
SW.WriteLine(cmdir)
SW.WriteLine(comando)
'Results = SR.ReadToEnd
'SW.Close()
'SR.Close()
'Invoke(Finished)
Next
SW.Close()
SR.Close()
End Sub
Private Sub UpdateText()
Dim midirectorio As String = TextBox1.Text
Dim strStreamW As Stream = Nothing
Dim strStreamWriter As StreamWriter = Nothing
Dim fecha As String = DateTime.Now.ToString("dd MMM HHmmss") & ".txt"
Windows.Forms.Cursor.Current = Cursors.WaitCursor
Dim rutarchivo As String = String.Concat(midirectorio, "log-", fecha)
strStreamW = File.Create(rutarchivo)
strStreamWriter = New StreamWriter(strStreamW, System.Text.Encoding.Default)
strStreamWriter.WriteLine(Results)
strStreamWriter.Close()
End Sub
Lo que dices sobre las líneas de código:
'Results = SR.ReadToEnd
'SW.Close()
'SR.Close()
'Invoke(Finished)
Una parte de eso ya te lo había dicho. No sé si recuerdes que te dije que eliminaras las líneas que cierran los streams. Y lo comentar la línea del invoke() y que funcione, pues tiene sentido. Lo que ocurre es que estás usando mal el delegado. Por alguna raón (no estoy seguro cual) sólo te funcionará el delegado la primera vez que lo utilices. Prueba dejando el bucle de la siguiente manera:
For Each file As String In My.Computer.FileSystem.GetFiles(midirectorio, FileIO.SearchOption.SearchAllSubDirectories, "*.T01")
nombre = My.Computer.FileSystem.GetName(file)
cmdir = "cd " & midirectorio
comando = "runpkr00.exe -d -s " & nombre
SW.WriteLine(cmdir)
SW.WriteLine(comando)
Results = SR.ReadToEnd
Finished = New delUpdate(AddressOf UpdateText)
Invoke(Finished)
Next
Es decir, asignando la dirección al delegado cada vez que lo quieras utilizar. En caso de que no te funcione puedes hacerlo dejando el código anterior como te lo dejé, pero eliminando la línea donde asignas la dirección del delegado. Y modificando la función UpdateText() de la siguiente manera:
Private Sub UpdateText()
If Me.InvokeRequired = False Then
Dim midirectorio As String = TextBox1.Text
Dim strStreamW As Stream = Nothing
Dim strStreamWriter As StreamWriter = Nothing
Dim fecha As String = DateTime.Now.ToString("dd MMM HHmmss") & ".txt"
Windows.Forms.Cursor.Current = Cursors.WaitCursor
Dim rutarchivo As String = String.Concat(midirectorio, "log-", fecha)
strStreamW = File.Create(rutarchivo)
strStreamWriter = New StreamWriter(strStreamW, System.Text.Encoding.Default)
strStreamWriter.WriteLine(Results)
strStreamWriter.Close()
Else
Dim D As delUpdate = new delUpdate(AddressOf UpdateText)
Me.Invoke(D)
End If
End Sub
Si cometí un error al escribir los nombres de las propiedades, busca las correctas (es que no estoy escribiendo desde Visual Studio).
Y sobre lo que dices del FileCopy(), la verdad no tengo idea de a qué se deba. ¿Qué error te da el depurador cuando la aplicación crashea?