c# - usar - Application.Current.Shutdown() no está matando a mi aplicación
wpf vs winforms (7)
Acabo de comenzar una nueva aplicación C # / WPF y estoy usando NotifyIcon del proyecto WPF Contrib . Puedo iniciar el programa, agregar un elemento de menú "Salir" al ContextMenu de NotifyIcon y vincular ese elemento a un método que simplemente ejecuta Application.Current.Shutdown ().
Esto cierra la ventana principal y el NotifyIcon, pero algo continúa ejecutándose, ejecutándose desde VS, no abandona el modo de depuración. ¿Qué sigue funcionando? ¿O cómo puedo comprobarlo?
EDITAR
Acabo de intentar agregar un botón que llama a Application.Current.Shutdown () y se cierra correctamente. Solo cuando se me llama desde NotifyIcon tengo un problema. ¿Por qué sería esto?
Para aclarar, tengo el siguiente XAML:
<Window x:Class="VirtualBoxManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:av="http://schemas.codeplex.com/wpfcontrib/xaml/presentation"
Title="VirtualBox Manager" Height="350" Width="525"
ShowInTaskbar="False" WindowStyle="None">
<Grid>
<av:NotifyIcon Icon="/icon/path"
Text="Virtual Machine Manager"
Name="notifyIcon">
<FrameworkElement.ContextMenu>
<ContextMenu>
<MenuItem Header="Exit" Click="MenuItemExit_Click" />
</ContextMenu>
</FrameworkElement.ContextMenu>
</av:NotifyIcon>
<Button Content="Button" Click="button1_Click" />
</Grid>
Tanto button1_Click como MenuItemExit_Click son idénticos, pero el primero sale exitosamente de la aplicación y el segundo no.
Experimentación adicional: incluso si muevo Application.Current.Shutdown () a otro método y lo llamo en su lugar, agregando una capa de direccionamiento indirecto, aún así el botón funciona y el icono no.
¿Solución encontrada?
Acabo de encontrar este hilo , cuya solución funciona aquí. No entiendo totalmente lo que está sucediendo, así que si a alguien le importa explicarlo, lo apreciaría.
¡No necesitas hacer eso! simplemente anule el método OnClosing
dentro de la ventana principal de esta manera:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
try
{
// there is a bug (throw CrossThreadException) in notifyIcon when disposing from ViewModel.
notifyIcon.Dispatcher.Invoke(new Action(delegate
{
notifyIcon.Dispose();
}));
}
catch { }
base.OnClosing(e);
}
y luego en cualquier parte del código de su aplicación principal, no importa que esté en View o ViewModel o en todas partes, simplemente llámelo así:
Application.Current.MainWindow.Close();
Tuve el mismo problema pero lo arreglé así.
Actualización: No debes usar Environment.Exit(0);
método. lanza la misma excepción.
Creo que la respuesta del autor es la mejor aquí, pero realmente no se ha llamado. Application.Shutdown()
parece requerir que se ejecute en el subproceso del despachador para funcionar. Intenta esto si te encuentras con el problema:
Application.Current.Dispatcher.Invoke(Application.Current.Shutdown);
Descubrí que si creo subprocesos que no están configurados en "fondo", la ventana principal / etc se cerrará, pero los subprocesos mantendrán rondas.
En otras palabras, solo los hilos de fondo se cierran cuando finaliza el hilo principal. Los subprocesos normales, también conocidos como Thread.IsBackground = false, mantendrán el proceso en ejecución.
Intente usar thread.IsBackground = true;
PS Supuse que usabas hilos en algún lugar.
He tenido el mismo problema en mi aplicación. En mi módulo de inicio (Startup.cs) encontré que esto funciona para mí:
Process.GetCurrentProcess().Kill();
El código es el siguiente:
class StartUp
{
[STAThread]
public static void Main()
{
try
{
Process[] processes = new Process[6];
App app = new App();
app.InitializeComponent();
app.Run();
Process.GetCurrentProcess().Kill(); //Must add this line after app.Run!!!
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
Esto va directamente al proceso que causa el bloqueo. No hay necesidad de iterar a través de múltiples procesos.
Puede estar viviendo en los procesos. Aquí hay una muestra de cómo controlo / mato el proceso.
const string str = "MRS_Admin";
foreach (Process process in Process.GetProcesses())
{
if (process.ProcessName.StartsWith(str))
{
Console.WriteLine(@"Killing process " + str);
process.Kill();
}
}
Usted puede intentar Environment.Exit(0);
Mata el proceso con el código de salida dado. El código de salida 0 indica que la aplicación terminó con éxito. Puede ser más "grosero" o "no hecho", pero quizás esto es lo que está buscando.
Asegúrese absolutamente de que no está creando ningún objeto de Windows que nunca muestre ()
Por alguna extraña razón, WPF agrega ventanas a Application.Windows
en CREATION y no cuando llama por primera vez a Show()
. Si tiene la Application.Current.Shutdown
establecida en ShutdownMode.OnLastWindowClose
, estas ventanas (que ni siquiera mostró) evitarán que la aplicación se cierre.
Digamos que abres una ventana secundaria de tu ventana principal como esta
Console.WriteLine("Window count : " + Application.Windows.Count);
var window = new OrderDetailsWindow();
Console.WriteLine("Window count : " + Application.Windows.Count);
window.Show();
Antes de llamar a Show()
verá que Applications.Windows ahora muestra 2. La aplicación solo se cerrará cuando Windows.Count sea cero.
Mi situación:
Tengo un WindowFactory que toma un modelo de vista y crea una ventana para el modelo pasado.
De alguna manera, a lo largo de los años, mi copia y pegado habían producido esto:
if (viewModel is DogModel)
{
window = new DogWindow();
}
else if (viewModel is CatViewModel)
{
window = new CatWindow();
}
if (viewModel is DogModel)
{
window = new DogWindow();
}
window.DataContext = viewModel;
window.Show();
Entonces, cuando viewModel
era DogModel
, terminé creando DOS objetos DogWindow
, de modo que Application.Windows.Count
tenía 3 cuando esperaba que fuera 2. Dado que Application.Shutdown
estaba esperando a que todas las ventanas se cerraran, nunca se activó, aunque ni siquiera ¡Abrí la ventana!
Siempre habría asumido que se necesitaba Show()
para activar la ventana, pero eso era una suposición errónea, por lo que mi aplicación nunca salió.