开发者

Application.Current.Shutdown() is not killing my application

开发者 https://www.devze.com 2023-02-13 01:10 出处:网络
I\'ve just started a new C#/WPF application and am using the NotifyIcon from the WPF Contrib project. I can start the program, add an \"Exit\" MenuItem to the NotifyIcon\'s ContextMenu, and link that

I've just started a new C#/WPF application and am using the NotifyIcon from the WPF Contrib project. I can start the program, add an "Exit" MenuItem to the NotifyIcon's ContextMenu, and link that item to a method that simply runs Application.Current.Shutdown().

This closes the main window and the NotifyIcon, but something continues to ru开发者_开发问答n - running from VS, it does not leave debug mode. What is still running? Or how can I check?

EDIT

I've just tried adding a button that calls Application.Current.Shutdown(), and that exits properly. It's only when called from the NotifyIcon that I have a problem. Why would this be?

To clarify, I have the following 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>

Both button1_Click and MenuItemExit_Click are identical, but the former successfully exits the app and the latter does not.

Further experimentation: even if I move Application.Current.Shutdown() into another method and call that instead, adding a layer of indirection, still the button works and the icon doesn't.

Solution found?

Just found this thread, who's solution does work here. I don't totally understand what's happening, so if anybody cares to explain I'd appreciate it.


You coult try Environment.Exit(0); It kills the process with the given exit code. Exit code 0 states the application terminated successfully. It might be more 'rude' or 'not-done' but perhaps this is what you are looking for.


I found if I create threads that are not set to "background", the main window/etc will close, but the threads will keep runnings.

In other words, only background threads close themselves when the main thread ends. Regular threads, aka Thread.IsBackground = false, will keep the process running.

Try using thread.IsBackground = true;

P.S. I made the assumption that you used threads somewhere.


I think the author's answer is the best one here, but hasn't really been called out. Application.Shutdown() seems to require to be executed on the dispatcher thread to work. Try this if you run into the problem:

Application.Current.Dispatcher.Invoke(Application.Current.Shutdown);


I have had the same problem in my application. In my start up module (Startup.cs) I found that this works for me:

Process.GetCurrentProcess().Kill();

The code is as follows:

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);
    }
    }

This goes directly to the process causing the hang. There is no need to iterate through multiple processes.


You don't need to do that! just simply override OnClosing method inside the main window like this:

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            try
            {
                // If you try to dispose it from ViewModel, you might get a CrossThreadException.
                notifyIcon.Dispatcher.Invoke(new Action(delegate
                {
                    notifyIcon.Dispose();
                }));
            }
            catch { }
            base.OnClosing(e);
        }

and then in everywhere of your main application code, no matter you are in View or ViewModel or everywhere, just call it like this:

Application.Current.MainWindow.Close();

I had the same problem but I fix it like that.

Update: You should not use Environment.Exit(0); method. it throws the same exception.


Make absolutely sure you aren't creating any Window objects that you never Show()

For some insane reason WPF adds windows to Application.Windows on CREATION and not when you first call Show(). If you have Application.Current.Shutdown set to ShutdownMode.OnLastWindowClose then these windows (that you never even displayed) will prevent the app from shutting down.

Lets say you open a child window of your main window like this

Console.WriteLine("Window count : " + Application.Windows.Count);
var window = new OrderDetailsWindow();
Console.WriteLine("Window count : " + Application.Windows.Count);
window.Show();

Before you even call Show() you'll see that Applications.Windows now shows 2. The app will only shutdown when Windows.Count is zero.


My situation:

I have a WindowFactory that takes a viewmodel and creates a window for the model passed in.

Somehow over the years my copy and pasting had yielded this :

 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();

So when viewModel was DogModel I ended up creating TWO DogWindow objects so Application.Windows.Count was 3 when I expected it to be 2. Since Application.Shutdown was waiting for all windows to be closed it never got activated - even though I never even opened the window!

I would always have assumed that Show() was needed to activate the window, but that was a wrong assumption - so my app never exited.


It may be living in the processes. Here's a sample of how I check / kill the process

       const string str = "MRS_Admin";
        foreach (Process process in Process.GetProcesses())
        {
            if (process.ProcessName.StartsWith(str))
            {
                Console.WriteLine(@"Killing process " + str);
                process.Kill();
            }
        }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号