Autor
|
Tema: EJECUTAR CMD EN APLICACIÓN .NET (Leído 6,861 veces)
|
rochro
Desconectado
Mensajes: 42
|
Buen día a todos, quisiera que me apoyen en poder ver cual es mi error ya que al momento de ejecutar la app se marca error en la linea txtResults.Text = SR.ReadToEnd. La idea es que en vez que se muestre en la ventana del cmd, figure en el cuadro de texto txtResults y sería mucho mejor si fuera continuo o sea el resultado de ping 127.0.0.1 -t figure en el cuadro de texto. Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click Dim CMDThread As New Threading.Thread(AddressOf CMDAutomate) CMDThread.Start() End Sub Private Sub CMDAutomate() Dim PROCESO As New Process Dim INFO As New System.Diagnostics.ProcessStartInfo INFO.FileName = "cmd" INFO.RedirectStandardInput = True INFO.RedirectStandardOutput = True INFO.UseShellExecute = False PROCESO.StartInfo = INFO PROCESO.Start() Dim SR As System.IO.StreamReader = PROCESO.StandardOutput Dim SW As System.IO.StreamWriter = PROCESO.StandardInput Dim comandoping As String = String.Concat("ping ", TextBox1.Text, ".", TextBox2.Text, ".", TextBox3.Text, ".", TextBox4.Text) SW.WriteLine(comandoping) SW.WriteLine("exit") txtResults.Text = SR.ReadToEnd SW.Close() SR.Close() End Sub
Gracias por todo. Saludos.
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
al momento de ejecutar la app se marca error en la linea txtResults.Text = SR.ReadToEnd. 1. Cuando tengas un error, por favor da los detalles necesarios para poder ayudarte. El mensaje exacto de error que te indica el debugger de VisualStudio. ya que de lo contrario estamos haciendo el paripé sin tener información precisa. Sea cual sea el error que te indique imagino que es porque estás intentando modificar un control desde un Thread distinto al Thread donde creaste el cotnrol. es decir, tienes el control txtResults en el thread "X" e intentas modificarlo desde el thread "Y", no puedes modificar un control así como así desde otro thread, primero debes comprobar si el control necesita ser invocado, y después, invocarlo. Ejemplo: Imports System.Threading.Tasks Public Class Form1 ''' <summary> ''' The CMD <see cref="System.Diagnostics.Process"/> instance. ''' </summary> Private WithEvents cmdProcess As New Process With { .EnableRaisingEvents = True, .StartInfo = New ProcessStartInfo With { .FileName = "cmd.exe", .Arguments = String.Empty, .RedirectStandardInput = False, .RedirectStandardOutput = True, .RedirectStandardError = True, .UseShellExecute = False, .CreateNoWindow = True } } ''' <summary> ''' Gets the ping commandline arguments. ''' </summary> Private ReadOnly Property PingArguments As String Get Return String.Format("ping.exe ""{0}.{1}.{2}.{3}""", TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text) End Get End Property Private Sub btnSend_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles btnsend.Click Task.Factory.StartNew(AddressOf CMDAutomate) End Sub Private Sub CMDAutomate() With Me.cmdProcess .StartInfo.Arguments = String.Format("/C ""{0}""", Me.PingArguments) .Start() .BeginOutputReadLine() .BeginErrorReadLine() .WaitForExit() End With End Sub ''' <summary> ''' Occurs when an application writes to its redirected <see cref="System.Diagnostics.Process.StandardOutput"/> stream. ''' Occurs when an application writes to its redirected <see cref="System.Diagnostics.Process.StandardError"/> stream. ''' </summary> Private Sub cmdProcess_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs) _ Handles cmdProcess.OutputDataReceived, cmdProcess.ErrorDataReceived Select Case txtResults.InvokeRequired Case True txtResults.Invoke(Sub() txtResults.AppendText("" & e.Data)) txtResults.Invoke(Sub() txtResults.AppendText(Environment.NewLine)) Case Else txtResults.AppendText(e.Data) txtResults.AppendText(Environment.NewLine) End Select ' Debug.WriteLine(e.Data) #End If End Sub ''' <summary> ''' Occurs when a <see cref="System.Diagnostics.Process"/> exits. ''' </summary> Private Sub cmdProcess_Exited(ByVal sender As Object, ByVal e As EventArgs) _ Handles cmdProcess.Exited Debug. WriteLine(String. Format("cmdProcess has exited with exit code: {0}", DirectCast(sender, Process).ExitCode)) End Sub End Class
Saludos
|
|
« Última modificación: 11 Noviembre 2014, 18:53 pm por Eleкtro »
|
En línea
|
|
|
|
rochro
Desconectado
Mensajes: 42
|
Sea cual sea el error que te indique imagino que es porque estás intentando modificar un control desde un Thread distinto al Thread donde creaste el cotnrol. es decir, tienes el control txtResults en el thread "X" e intentas modificarlo desde el thread "Y", no puedes modificar un control así como así desde otro thread, primero debes comprobar si el control necesita ser invocado, y después, invocarlo.
Woww.. en serio eres un capo en esto. Muchas gracias por tu ayuda. Era exactamente lo que queria. Prometo que seré mas cuidadosa con mis publicaciones y poner la información completa. Gracias por todo.
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
De nada, para eso estamos, de todas formas esto que te expliqué es quizás lo más básico de la programación asíncrona en .Net. Se me olvidó comentar algo importante para que no te pierdas en el largo código que te mostré (en caso de que te hayas perdido un poco xD), todo ese código es solo una mejora del código que tú publicaste... por si lo quieres usar de esa manera (suscribiéndote a los eventos de la instancia del proceso), pero lo importante del código es lo siguiente, donde llamo a la propiedad .Invokerequired y el método .Invoke desde el subproceso/thread secundario: ... Select Case txtResults.InvokeRequired Case True txtResults.Invoke(Sub() txtResults.AppendText("" & e.Data)) txtResults.Invoke(Sub() txtResults.AppendText(Environment.NewLine)) Case Else txtResults.AppendText(e.Data) txtResults.AppendText(Environment.NewLine) End Select ...
⇲Control.InvokeRequired Property - MSDNControl.Invoke(Lambda) Method - MSDNSaludos
|
|
« Última modificación: 11 Noviembre 2014, 19:43 pm por Eleкtro »
|
En línea
|
|
|
|
rochro
Desconectado
Mensajes: 42
|
De nada, para eso estamos, de todas formas esto que te expliqué es quizás lo más básico de la programación asíncrona en .Net.
Tengo un inconveniente y quisiera que me ayudes. En el código que me entregaste sólo aumenté el -t al comando ping pero al crear un linklabel para que vacie los campos, el comando ping se sigue ejecutando. Como lo puedo parar? ... Private ReadOnly Property PingArguments As String Get Return String.Format("ping.exe ""{0}.{1}.{2}.{3}"" -t", TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text) End Get End Property ... Private Sub LinkLabel1_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked Dim x As Control For Each x In Me.Controls If TypeOf x Is System.Windows.Forms.TextBox Then x.Text = "" Next End Sub
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
Como lo puedo parar? Depende. 1) ¿Al clickar en el linklabel es cuando quieres detener Ping? Debes detener la ejecución del thread que está corriendo la cmd, si estás usando la Class Thread entonces puedes llamar al método Thread.Abort, si estás usando la class Tasks entonces puedes llamar al método Task.Cancel usando un token de cancelación para esa Task. O también puedes hacerlo desde la winAPi, con la función TerminateThread: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686717%28v=vs.85%29.aspx2) ¿Estás usando la misma Task del código que te mostré?; Muestra el resto del código relevante, es decir, la declaración del thread y el método del thread (donde ejecutas la cmd) EDITO: De todas formas hace tiempo escribí un ejemplo de uso de la class Tasks para cancelar una Task, te podría servir hasta nueva respuesta: #Region " TASK Example " Public Class Form1 ' NORMAL TASK USAGE: ' ------------------ Private Task1 As Threading.Tasks.Task Private Task1CTS As New Threading.CancellationTokenSource Private Task1CT As Threading.CancellationToken = Task1CTS.Token Private Sub MyTask1(ByVal CancellationToken As Threading.CancellationToken) For x As Integer = 0 To 9999 If Not CancellationToken.IsCancellationRequested Then Debug. Print("Task1: " & x ) Else MsgBox(String.Format("Task1 Canceled at ""{0}""", x)) Exit Sub End If Next x End Sub ' ANONYMOUS TASK METHOD: ' --------------------- Private Task2 As Threading.Tasks.Task Private Task2CTS As New Threading.CancellationTokenSource Private Task2CT As Threading.CancellationToken = Task2CTS.Token Private Delegate Function Task2Delegate(ByVal CancellationToken As Threading.CancellationToken) Private MyTask2 As Task2Delegate = Function(CancellationToken As Threading.CancellationToken) As Boolean For x As Integer = 0 To 9999 If Not CancellationToken.IsCancellationRequested Then Debug. Print("Task2: " & x ) Else MsgBox(String.Format("Task2 Canceled at ""{0}""", x)) Return False End If Next x Return True End Function Private Sub TaskTest() Handles MyBase.Shown ' Run an asynchronous Task. Task1 = Threading.Tasks.Task.Factory.StartNew(Sub() MyTask1(Task1CT), Task1CT) ' Wait 2 seconds (Just to demonstrate this example) Threading.Thread.Sleep(2 * 1000) ' Cancel the Task. Task1CTS.Cancel() ' Wait for the Task to finish the being cancelled. Task1.Wait() ' Show the task status MsgBox(Task1.Status.ToString) ' Result: RanToCompletion ' ReStart the Task1. Task1 = Threading.Tasks.Task.Factory.StartNew(Sub() MyTask1(Task1CT), Task1CT) ' Start the Task2 Task2 = Threading.Tasks.Task.Factory.StartNew(Of Boolean)(Function() MyTask2(Task2CT), Task2CT) ' Wait for both Tasks to finish their execution. Threading.Tasks.Task.WaitAll() End Sub End Class #End Region
Saludos
|
|
« Última modificación: 12 Noviembre 2014, 18:31 pm por Eleкtro »
|
En línea
|
|
|
|
rochro
Desconectado
Mensajes: 42
|
Depende.
1) ¿Al clickar en el linklabel es cuando quieres detener Ping?
Si. Quiero que al hacer clic en el linklabel se cancele el task. Trato de entender el código pero ya me confundí Disculpa por tanta molestia elektro.
|
|
« Última modificación: 13 Noviembre 2014, 16:35 pm por rochro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
No es ninguna molestía, ayudar es mi hobbie favorito (y más cuando se trata de VB.Net) He añadido el método StartTask, CancelTask, y el linklabel al código que mostré arriba, aquí esta todo lo necesario: Imports System.Threading Imports System.Threading.Tasks Public Class Form1 Private cmdTask As Task Private cmdTaskCTS As New CancellationTokenSource Private cmdTaskCT As CancellationToken ''' <summary> ''' The CMD <see cref="System.Diagnostics.Process"/> instance. ''' </summary> Private WithEvents cmdProcess As New Process With { .EnableRaisingEvents = True, .StartInfo = New ProcessStartInfo With { .FileName = "cmd.exe", .Arguments = String.Empty, .RedirectStandardInput = False, .RedirectStandardOutput = True, .RedirectStandardError = True, .UseShellExecute = False, .CreateNoWindow = True } } ''' <summary> ''' Gets the ping commandline arguments. ''' </summary> Private ReadOnly Property PingArguments As String Get Return String.Format("ping.exe -t ""{0}.{1}.{2}.{3}""", TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text) End Get End Property Private Sub btnSend_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles btnsend.Click Me.StartTask() End Sub Private Sub CMDAutomate() With Me.cmdProcess .StartInfo.Arguments = String.Format("/C ""{0}""", Me.PingArguments) .Start() .BeginOutputReadLine() .BeginErrorReadLine() .WaitForExit(Integer.MaxValue) End With End Sub ''' <summary> ''' Occurs when an application writes to its redirected <see cref="System.Diagnostics.Process.StandardOutput"/> stream. ''' Occurs when an application writes to its redirected <see cref="System.Diagnostics.Process.StandardError"/> stream. ''' </summary> Private Sub cmdProcess_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs) _ Handles cmdProcess.OutputDataReceived, cmdProcess.ErrorDataReceived Select Case txtresults.InvokeRequired Case True txtresults.Invoke(Sub() txtresults.AppendText("" & e.Data)) txtresults.Invoke(Sub() txtresults.AppendText(Environment.NewLine)) Case Else txtresults.AppendText(e.Data) txtresults.AppendText(Environment.NewLine) End Select ' Debug.WriteLine(e.Data) #End If End Sub ''' <summary> ''' Occurs when a <see cref="System.Diagnostics.Process"/> exits. ''' </summary> Private Sub cmdProcess_Exited(ByVal sender As Object, ByVal e As EventArgs) _ Handles cmdProcess.Exited Debug. WriteLine(String. Format("cmdProcess has exited with exit code: {0}", DirectCast(sender, Process).ExitCode)) End Sub Private Sub LinkLabel1_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) _ Handles LinkLabel1.LinkClicked ' limpio el texto de cada textbox. For Each tb As TextBox In Me.Controls.OfType(Of TextBox)() tb.Clear() Next tb ' cancelo la tarea en segundo plano. Me.CancelTask() End Sub Private Sub StartTask() Me.cmdTask = Task.Factory.StartNew(AddressOf CMDAutomate) Me.cmdTaskCTS = New Threading.CancellationTokenSource Me.cmdTaskCT = cmdTaskCTS.Token End Sub Private Sub CancelTask() ' Si el proceso no se ha detenido... If Not Me.cmdProcess.HasExited Then With Me.cmdProcess ' cancelo la lectura de los outputs. .CancelOutputRead() .CancelErrorRead() .Kill() ' mato el proceso (cmd.exe) End With ' Cancelo la tarea en segundo plano. Me.cmdTaskCTS.Cancel() ' Espero a que la tarea se haya cancelado. Me.cmdTask.Wait() End If End Sub End Class
EDITO: Fíjate que también cambié esto en el método CMDAutomate, para que funcionase del modo esperado: .WaitForExit(Integer.MaxValue)
Saludos.
|
|
« Última modificación: 13 Noviembre 2014, 17:04 pm por Eleкtro »
|
En línea
|
|
|
|
rochro
Desconectado
Mensajes: 42
|
No es ninguna molestía, ayudar es mi hobbie favorito (y más cuando se trata de VB.Net) Gracias Elektro. Como que ya voy entendiendo un poco este tema de los tasks. Ahora no se como hacer, ya que como se va avanzando con esta pequeña app se me ocurre si hay alguna manera de que grabe los datos del textbox y por mas que se cierre y vuelva a abrir aparece con esos valores hasta que se cambie. Gracias por tu atención
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
se me ocurre si hay alguna manera de que grabe los datos del textbox y por mas que se cierre y vuelva a abrir aparece con esos valores hasta que se cambie. Hay muchas maneras de hacer eso, lo que más sencillo te resultará es utilizar la infrastructura de My.Settings. Puedes crear la propiedad desde las opciones del proyecto, y luego acceder a dicha propiedad en tiempo de ejecución para guardar/cargar valores. Es muy sencillo, pero lee un poco acerca de ello para enterarte: Managing Application SettingsUsing My.Settings in Visual Basic 2005How to: Change User Settings in Visual BasicSaludos
|
|
« Última modificación: 18 Noviembre 2014, 18:38 pm por Eleкtro »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Ejecutar una aplicacion en Web
Programación Visual Basic
|
CsarGR
|
4
|
2,278
|
2 Abril 2007, 16:23 pm
por ~~
|
|
|
Ejecutar aplicacion (Winsock)
Programación Visual Basic
|
mdg
|
2
|
1,938
|
26 Diciembre 2007, 23:55 pm
por ~~
|
|
|
Ejecutar aplicacion externa con c#
.NET (C#, VB.NET, ASP)
|
kateme
|
1
|
8,642
|
11 Septiembre 2008, 19:29 pm
por MANULOMM
|
|
|
Problemas al ejecutar aplicacion .net en XP
.NET (C#, VB.NET, ASP)
|
Skeletron
|
9
|
7,088
|
18 Mayo 2009, 13:13 pm
por Meta
|
|
|
Ejecutar desde PHP una aplicación GUI
GNU/Linux
|
SnakeDrak
|
2
|
2,859
|
24 Octubre 2010, 23:05 pm
por SnakeDrak
|
|