Autor
|
Tema: Problema con función Shell en VB.NET 2010 (Leído 5,867 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 Sub End Class
|
|
« Última modificación: 22 Diciembre 2015, 02:05 am por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.885
|
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 Sub End Class
|
|
« Última modificación: 26 Diciembre 2015, 03:13 am por Eleкtro »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.885
|
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 ContinueWithTask.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 Sub End Class
PD: Disculpen por la demora en responder.
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.885
|
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,342
|
6 Enero 2006, 23:46 pm
por Gangrel
|
|
|
Problema con una shell C99
« 1 2 »
Nivel Web
|
djcanuto
|
14
|
9,451
|
25 Junio 2010, 16:18 pm
por Debci
|
|
|
Llamar a función de Shell Extension Context Menu Handler.
Programación C/C++
|
APOKLIPTICO
|
5
|
10,815
|
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,371
|
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,506
|
22 Diciembre 2015, 02:06 am
por Eleкtro
|
|