| 
	
		|  Autor | Tema: Problema con función Shell en VB.NET 2010  (Leído 6,319 veces) |  
	| 
			| 
					
						| bybaal 
								
								 Desconectado 
								Mensajes: 52
								
								
								
								
								
								   | 
 
Necesito ejecutar una aplicación con la función shell, utilizando el parámetro Wait = True, hacer esto mientras un timer cambia constantemente la propiedad Text del Formulario. El problema es que mientras se espera a que termine dicha aplicación, el timer deja de actualizar la propiedad Text del Formulario. Aquí les dejo el código de ejemplo para ver si alguien puede ayudarme Public Class Form1    Dim WithEvents tmrEfect As New Timer With {.Enabled = True, .Interval = 1000}     Private Sub tmrEfect_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrEfect.Tick        Me.Text = Now    End Sub     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click        Shell("calc.exe", AppWinStyle.NormalFocus, True)        MsgBox("cerrada la aplicación")    End SubEnd Class
 
 |  
						| 
								|  |  
								| « Última modificación: 22 Diciembre 2015, 02:05 am por Eleкtro » |  En línea | 
 
 |  |  |  | 
			| 
					
						| Eleкtro 
								Ex-Staff    Desconectado 
								Mensajes: 9.964
								
								   | 
 
Buenas! 1. Por favor, postea las preguntas de Vb.Net en la sección correcta. (hay muchos posts movidos que deberían haberte dado ya una pista...) 2. Debes utilizar las etiquetas Geshi para insertar código, lee las reglas del foro de programación general, gracias. 
 Es normal lo que te ocurre, ya que cuando activas el parámetro "wait", el hilo propietario desde el que has realizado la llamada se detiene por tiempo indefinido hasta que el proceso finalize su ejecución. Para solucionar el problema que has descrito se me ocurren al menos dos maneras distintas, pero antes de nada por cuestiones de productividad, rendimiento, y adquisición de buenas costumbres, te aconsejo parar ahora mismo de utilizar la función Microsoft.VisualBasic.Shell  y cualquier otro miembro de ese espacio de nombres; reemplazalo por el uso de la Class System.Diagnostics.Process . 1. Puedes iniciar el proceso de la siguiente manera: Threading.Tasks.Task.Factory.StartNew(    Sub()        Using p As New Process            p.StartInfo.FileName = "calc.exe"            p.StartInfo.WindowStyle = ProcessWindowStyle.Normal            p.Start()            p.WaitForExit()        End Using         MessageBox.Show("cerrada la aplicación", "Calc.exe",                        MessageBoxButtons.OK, MessageBoxIcon.Information)     End Sub, TaskCreationOptions.None)
 Nota: En otras circunstancias tal vez podrias preferir utilizar el flag TaskCreationOptions.LongRunning  para forzar la creación de un nuevo hilo en el grupo de hilos por defecto, ganando así más velocidad de inicialización de la tarea al no esperar en la cola de hilos. 2. O puedes suscribirte al evento Process.Exited : Friend WithEvents Calc As Process Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click     Calc = New Process    Calc.EnableRaisingEvents = True    Calc.StartInfo.FileName = "calc.exe"    Calc.StartInfo.WindowStyle = ProcessWindowStyle.Normal    Calc.Start() End Sub Private Sub Calc_Exited() Handles Calc.Exited     MessageBox.Show("cerrada la aplicación", "Calc.exe",                            MessageBoxButtons.OK, MessageBoxIcon.Information)     ' Seguir con la lógica aquí... End Sub
 Saludos
 
 |  
						| 
								|  |  
								| « Última modificación: 22 Diciembre 2015, 04:00 am por Eleкtro » |  En línea | 
 
 |  |  |  | 
			| 
					
						| bybaal 
								
								 Desconectado 
								Mensajes: 52
								
								
								
								
								
								   | 
 
Muchas Gracias, Muy buena la ayuda una explicación de libro. Buenas! 1. Por favor, postea las preguntas de Vb.Net en la sección correcta. (hay muchos posts movidos que deberían haberte dado ya una pista...) 2. Debes utilizar las etiquetas Geshi para insertar código, lee las reglas del foro de programación general, gracias. 
 Es normal lo que te ocurre, ya que cuando activas el parámetro "wait", el hilo propietario desde el que has realizado la llamada se detiene por tiempo indefinido hasta que el proceso finalize su ejecución. Para solucionar el problema que has descrito se me ocurren al menos dos maneras distintas, pero antes de nada por cuestiones de productividad, rendimiento, y adquisición de buenas costumbres, te aconsejo parar ahora mismo de utilizar la función Microsoft.VisualBasic.Shell  y cualquier otro miembro de ese espacio de nombres; reemplazalo por el uso de la Class System.Diagnostics.Process . 1. Puedes iniciar el proceso de la siguiente manera: Threading.Tasks.Task.Factory.StartNew(    Sub()        Using p As New Process            p.StartInfo.FileName = "calc.exe"            p.StartInfo.WindowStyle = ProcessWindowStyle.Normal            p.Start()            p.WaitForExit()        End Using         MessageBox.Show("cerrada la aplicación", "Calc.exe",                        MessageBoxButtons.OK, MessageBoxIcon.Information)     End Sub, TaskCreationOptions.None)
 Nota: En otras circunstancias tal vez podrias preferir utilizar el flag TaskCreationOptions.LongRunning  para forzar la creación de un nuevo hilo en el grupo de hilos por defecto, ganando así más velocidad de inicialización de la tarea al no esperar en la cola de hilos. 2. O puedes suscribirte al evento Process.Exited : Friend WithEvents Calc As Process Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click     Calc = New Process    Calc.EnableRaisingEvents = True    Calc.StartInfo.FileName = "calc.exe"    Calc.StartInfo.WindowStyle = ProcessWindowStyle.Normal    Calc.Start() End Sub Private Sub Calc_Exited() Handles Calc.Exited     MessageBox.Show("cerrada la aplicación", "Calc.exe",                            MessageBoxButtons.OK, MessageBoxIcon.Information)     ' Seguir con la lógica aquí... End Sub
 Saludos |  
						| 
								|  |  
								|  |  En línea | 
 
 |  |  |  | 
			| 
					
						| bybaal 
								
								 Desconectado 
								Mensajes: 52
								
								
								
								
								
								   | 
 
Siento tener que revivir este tema, pero la verdad es que a pesar de que el código funciona perfectamente, no he podido adaptarlo a lo que necesito, discúlpenme. Anteriormente en VB6 yo usaba una función para ejecutar aplicaciones y esperar a que estas se cerrasen para continuar ejecutando el código de mi programa, sin que esto detuviera los timers que yo usaba en mi proyecto. Ahora en VB.NET como adapto este código para poder usarlo varías veces seguidas dentro de un mismo evento. Ejemplo: Imports System.Threading.Tasks Public Class Form1     Dim WithEvents tmrEfect As New Timer With {.Enabled = True, .Interval = 1000}     Private Sub tmrEfect_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrEfect.Tick        Me.Text = Now    End Sub     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click        RunWait("calc.exe", ProcessWindowStyle.Normal)        'Aquí necesito poner varias líneas de código de tienen que ejecutarse al cerrarce la calculadora        MsgBox("aplicación calc.exe cerrada")         RunWait("mspaint.exe", ProcessWindowStyle.Normal)        'Aquí necesito poner varias líneas de código de tienen que ejecutarse al cerrarce el paint        MsgBox("aplicación mspaint.exe cerrada")    End Sub     Private Sub RunWait(ByVal FullPathFile As String, ByVal WindowStyle As ProcessWindowStyle)        Threading.Tasks.Task.Factory.StartNew(            Sub()                Using p As New Process                    p.StartInfo.FileName = FullPathFile                    p.StartInfo.WindowStyle = WindowStyle                    p.Start()                    p.WaitForExit()                End Using            End Sub, TaskCreationOptions.None)    End SubEnd Class
 |  
						| 
								|  |  
								| « Última modificación: 26 Diciembre 2015, 03:13 am por Eleкtro » |  En línea | 
 
 |  |  |  | 
			| 
					
						| Eleкtro 
								Ex-Staff    Desconectado 
								Mensajes: 9.964
								
								   | 
 
2. Debes utilizar las etiquetas Geshi para insertar código, lee las reglas del foro de programación general, gracias. Si el próximo mensaje con código incumple la regla que ya conoces, será eliminado    lo siento. 
 Puedes "concatenar" la tarea con otra tarea de continuación asíncrona, utilizando la función ContinueWith Task.Factory.StartNew(    Sub()        Using p As New Process            p.StartInfo.FileName = "calc.exe"            p.StartInfo.WindowStyle = ProcessWindowStyle.Normal            p.Start()            p.WaitForExit()        End Using    End Sub, TaskCreationOptions.None).ContinueWith(    Sub()        MessageBox.Show("calc.exe has exited.")    End Sub)
 O simplemente esperar a que finalice la tarea: Private Function RunWait(ByVal fullPathFile As String, ByVal windowStyle As ProcessWindowStyle) As Task     Dim processTask As Action =        Sub()            Using p As New Process                p.StartInfo.FileName = fullPathFile                p.StartInfo.WindowStyle = windowStyle                p.Start()                p.WaitForExit()            End Using        End Sub     Return New Task(processTask) End Function
 ... Sub Test()... Handles...     Dim t As Task = RunWait("calc.exe", ProcessWindowStyle.Normal)    t.Start()    t.Wait()     MessageBox.Show("calc.exe has exited.") End Sub
 PD: La primera solución tiene la ventaja de no bloquear el thread propietario de la llamada a esa Task. Saludos |  
						| 
								|  |  
								| « Última modificación: 26 Diciembre 2015, 03:30 am por Eleкtro » |  En línea | 
 
 |  |  |  | 
			| 
					
						| bybaal 
								
								 Desconectado 
								Mensajes: 52
								
								
								
								
								
								   | 
 
Eso es exactamente lo que necesito, sólo queda un pequeño detalle, que para mi es el más problemático y para que puedan ayudarme, voy a tratar de explicar mejor lo que quiero hacer.  El programa ejecuta varias aplicaciones a lo largo de un procedimiento y es espera a que terminen cada una de ellas para poder continuar con el resto del código. Hasta aquí vamos bien con lo logrado hasta ahora, el problema es que mientras se espera a que las aplicaciones terminen un timer tiene que ir haciendo cambios en el formulario, como uso en el ejemplo cambiar el texto del titulo del form, pero puede ser cualquier otra cosa para indicar que el programa está funcionando, como pudiera ser también cambiar la imagen de un picturebox para mostrar una secuencia de imágenes de un reloj de arena. Por ejemplo: Imports System.Threading.Tasks Public Class Form1    Dim WithEvents tmrEfect As New Timer With {.Enabled = True, .Interval = 1000}     Private Function RunWait(ByVal fullPathFile As String, ByVal windowStyle As ProcessWindowStyle) As Task         Dim processTask As Action =            Sub()                Using p As New Process                    p.StartInfo.FileName = fullPathFile                    p.StartInfo.WindowStyle = windowStyle                    p.Start()                    p.WaitForExit()                End Using            End Sub         Return New Task(processTask)     End Function     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click        Dim t As Task = RunWait("calc.exe", ProcessWindowStyle.Normal)        t.Start()        t.Wait()        MessageBox.Show("calc.exe has exited.")         t = RunWait("mspaint.exe", ProcessWindowStyle.Normal)        t.Start()        t.Wait()        MessageBox.Show("mspaint.exe has exited.")    End Sub     Private Sub tmrEfect_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrEfect.Tick        Me.Text &= "."        If Len(Me.Text) = 10 Then Me.Text = "Espere"    End Sub     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load        Me.Text = "Espere"    End SubEnd Class 
 PD: Disculpen por la demora en responder. |  
						| 
								|  |  
								|  |  En línea | 
 
 |  |  |  | 
			| 
					
						| Eleкtro 
								Ex-Staff    Desconectado 
								Mensajes: 9.964
								
								   | 
 
Private ReadOnly title As String = "Espere"Friend WithEvents TimerEfect As Global.System.Windows.Forms.Timer Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load     Me.Text = Me.title    Me.TimerEfect = New Global.System.Windows.Forms.Timer With {.Enabled = True, .Interval = 1000} End Sub Private Sub TimerEfect_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles TimerEfect.Tick     If Me.Text.EndsWith("...") Then        Me.Text = Me.title     Else        Me.Text &= "."     End If End Sub Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click     Task.Factory.StartNew(        Sub()            Dim t As Task = RunWait("calc.exe", ProcessWindowStyle.Normal)            t.Start()            t.Wait()            MessageBox.Show("calc.exe has exited.")             t = RunWait("mspaint.exe", ProcessWindowStyle.Normal)            t.Start()            t.Wait()            MessageBox.Show("mspaint.exe has exited.")        End Sub) End Sub Private Function RunWait(ByVal fullPathFile As String, ByVal windowStyle As ProcessWindowStyle) As Task     Dim processTask As Action =        Sub()            Using p As New Process                p.StartInfo.FileName = fullPathFile                p.StartInfo.WindowStyle = windowStyle                p.Start()                p.WaitForExit()            End Using        End Sub     Return New Task(processTask) End Function
 Saludos |  
						| 
								|  |  
								|  |  En línea | 
 
 |  |  |  | 
			| 
					
						| bybaal 
								
								 Desconectado 
								Mensajes: 52
								
								
								
								
								
								   | 
 
Ahora si quedó perfecto. Muchas gracias por la ayuda y por aguantar tantas molestias Private ReadOnly title As String = "Espere"Friend WithEvents TimerEfect As Global.System.Windows.Forms.Timer Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load     Me.Text = Me.title    Me.TimerEfect = New Global.System.Windows.Forms.Timer With {.Enabled = True, .Interval = 1000} End Sub Private Sub TimerEfect_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles TimerEfect.Tick     If Me.Text.EndsWith("...") Then        Me.Text = Me.title     Else        Me.Text &= "."     End If End Sub Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click     Task.Factory.StartNew(        Sub()            Dim t As Task = RunWait("calc.exe", ProcessWindowStyle.Normal)            t.Start()            t.Wait()            MessageBox.Show("calc.exe has exited.")             t = RunWait("mspaint.exe", ProcessWindowStyle.Normal)            t.Start()            t.Wait()            MessageBox.Show("mspaint.exe has exited.")        End Sub) End Sub Private Function RunWait(ByVal fullPathFile As String, ByVal windowStyle As ProcessWindowStyle) As Task     Dim processTask As Action =        Sub()            Using p As New Process                p.StartInfo.FileName = fullPathFile                p.StartInfo.WindowStyle = windowStyle                p.Start()                p.WaitForExit()            End Using        End Sub     Return New Task(processTask) End Function
 Saludos |  
						| 
								|  |  
								|  |  En línea | 
 
 |  |  |  |  |  
 
	
 
 
				
					
						| Mensajes similares |  
						|  | Asunto | Iniciado por | Respuestas | Vistas | Último mensaje |  
						|   |   | Problema con Shell Programación Visual Basic
 | ezdookie | 6 | 2,587 |  6 Enero 2006, 23:46 pm por Gangrel
 |  
						|   |   | Problema con una shell C99
							« 1 2 » Nivel Web
 | djcanuto | 14 | 10,054 |  25 Junio 2010, 16:18 pm por Debci
 |  
						|   |   | Llamar a función de Shell Extension Context Menu Handler. Programación C/C++
 | APOKLIPTICO | 5 | 11,229 |  20 Diciembre 2011, 16:06 pm por Eternal Idol
 |  
						|   |   | llamar funcion equivalente a shell desde window mobile .NET (C#, VB.NET, ASP)
 | sysfactory | 1 | 2,697 |  18 Julio 2013, 06:14 am por Eleкtro
 |  
						|   |   | MOVIDO: Problema con función Shell en VB.NET 2010 Programación Visual Basic
 | Eleкtro | 0 | 1,660 |  22 Diciembre 2015, 02:06 am por Eleкtro
 |    |