简体   繁体   中英

Closing Application Using C#

I am Using a Form Application and I want to know how can I exit environment if the process conquer.exe was closed. I am Using this Code in a Timer but nothing happens if conquer.exe was closed.

foreach (System.Diagnostics.Process exe in System.Diagnostics.Process.GetProcesses())
{
    if (exe.ProcessName.StartsWith("conquer"))
    {
        exe.WaitForExit();
        if (exe.HasExited)
        {
            Application.Exit();
            Environment.Exit(0);
        }
    }
}

As @Steven Liekens suggested,We can use the Process.Exited event to keep track of the application state.

Create a list to store all the processes with same name.

List<Process> selectedProcesses = new List<Process>();

Then get all the processes with same name.

        // Gets the processes with given name
        // If one or more instances are running
        foreach (Process exe in Process.GetProcesses())
        {
            if (exe.ProcessName.Contains("WINWORD"))
            {
                exe.Exited += exe_Exited;
                selectedProcesses.Add(exe);
            }
        }

Then in the Exited event check whether the list is empty.

    void exe_Exited(object sender, EventArgs e)
    {
        // If all the procees have been exited
        if (selectedProcesses.Count == 0)
        {
            Environment.Exit(0);
        }
        // Else remove a process from the list
        selectedProcesses.RemoveAt(selectedProcesses.Count - 1) ;
    }

You can try following

private ManagementEventWatcher WatchForProcessEnd(string processName)
    {
        string queryString =
            "SELECT TargetInstance" +
            "  FROM __InstanceDeletionEvent " +
            "WITHIN  10 " +
            " WHERE TargetInstance ISA 'Win32_Process' " +
            "   AND TargetInstance.Name = '" + processName + "'";

        // The dot in the scope means use the current machine
        string scope = @"\\.\root\CIMV2";

        // Create a watcher and listen for events
        ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
        watcher.EventArrived += ProcessEnded;
        watcher.Start();
        return watcher;
    }

    private void ProcessEnded(object sender, EventArrivedEventArgs e)
    {
        ManagementBaseObject targetInstance = (ManagementBaseObject) e.NewEvent.Properties["TargetInstance"].Value;
        string processName = targetInstance.Properties["Name"].Value.ToString();
        Console.WriteLine(String.Format("{0} process ended", processName));
    }

Source : .NET Events for Process executable start

Try this:

Process exe = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.ToLower().Trim().StartsWith("conquer"));
if(exe != null)
{
    exe.WaitForExit();
    exe.refresh();
    if(exe.HasExited)
    {
        Application.Exit();
        Enviroment.Exit(0);
    }
}
else
{
    //Conquer process has already exited or was not running.
}

I also agree with @Naren this code should be run in a background worker thread. You shouldn't need to run this in a timer, in fact you shouldn't. If you run this is a background worker thread the exe.WaitForExit(); call will suspend the background thread until the process has exited.

If the application you are running this code in is dependant on the conquer process then if it is not running on startup you could start it yourself and then wait for exit... Again this code should be run in a background thread.

Process exe = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.ToLower().Trim().StartsWith("conquer"));
if(exe == null)
{
    exe = new Process();
    exe.StartInfo.FileName = "conquer.exe"
    exe.Start();

    exe.WaitForExit();
    exe.refresh();
    if(exe.HasExited)
    {
        Application.Exit();
        Enviroment.Exit(0);
    }
}
if(exe != null)
{
    exe.WaitForExit();
    exe.refresh();
    if(exe.HasExited)
    {
        Application.Exit();
        Enviroment.Exit(0);
    }
}

It's not likely you'll be able to actually catch the process exiting if you are doing this in a timer. If you miss the process being exited, it won't be returned as a result of getting the running processes in your for loop. Because it never find it you will never find any process starting with "conquer".

A safer option is just to check if the process is in the list of running applications and exit if you can't find it.

using System.Linq;

if (!System.Diagnostics.Process.GetProcesses().Any(p => p.ProcessName.Equals("conquer.exe", System.StringComparison.OrdinalIgnoreCase)))
{
  Application.Exit();
}

Be careful of using StartsWith since you could mistakenly pick up other processes starting the with name "conquer".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM