简体   繁体   English

使用C#关闭应用程序

[英]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. 我正在使用表单应用程序,我想知道如果进程conquer.exe关闭,我该如何退出环境。 I am Using this Code in a Timer but nothing happens if conquer.exe was closed. 我在计时器中使用此代码但是如果conquer.exe已关闭则没有任何反应。

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. 正如@Steven Liekens所建议的那样,我们可以使用Process.Exited事件来跟踪应用程序状态。

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. 然后在Exited事件中检查列表是否为空。

    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 来源: 用于Process可执行启动的.NET事件

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. 我也同意@Naren这个代码应该在后台工作线程中运行。 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(); 如果你运行这是一个后台工作线程exe.WaitForExit(); call will suspend the background thread until the process has exited. call将暂停后台线程,直到进程退出。

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. 如果您错过了退出的进程,则不会因为在for循环中获取正在运行的进程而返回该进程。 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". 小心使用StartsWith,因为你可能会错误地选择以名称“conquer”开头的其他进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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