Home > Software engineering >  Process.Exited never fires
Process.Exited never fires

Time:04-13

I created a generic class to execute a console application while redirecting its output to a RichTextBox in my form.

The code works just fine, but the Process.Exited event never fires even though the console application exists normally after it completes it function.

Also, WaitForExit doesn't seem to do anything and any code I write after it is never executed for some reason.

Here's the class (updated):

using System;
using System.Diagnostics;

public class ConsoleProcess
{
    private string fpath;
    public ConsoleProcess(string filePath)
    {
        fpath = filePath;
    }

    public void Run(string arguments)
    {
        var procInfo = new ProcessStartInfo()
        {
            FileName = fpath,
            Arguments = arguments,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true,
            WindowStyle = ProcessWindowStyle.Hidden
        };

        var proc = new Process() { EnableRaisingEvents = true, StartInfo = procInfo };

        proc.OutputDataReceived  = Proc_DataReceived;
        proc.ErrorDataReceived  = Proc_DataReceived;
        proc.Exited  = Proc_Exited;

        proc.Start();
        proc.BeginOutputReadLine();
        proc.BeginErrorReadLine();
    }

    public event EventHandler<EventArgs>? ProcessExited;
    private void Proc_Exited(object? sender, EventArgs e)
    {
        ProcessExited?.Invoke(sender, e);
    }

    public event EventHandler<DataReceivedEventArgs>? DataReceived;
    private void Proc_DataReceived(object sender, DataReceivedEventArgs e)
    {
        DataReceived?.Invoke(sender, e);
    }
}

Here's the code I use in the Form:

        ConsoleProcess process = new("console_app.exe");
        process.DataReceived  = Process_DataReceived;
        process.ProcessExited  = Process_Exited;

        private async void Execute()
        {
            await Task.Run(() =>
            {
                process.Run("--arguments");
            });
        }

        private void Process_DataReceived(object? sender, System.Diagnostics.DataReceivedEventArgs e)
        {
            //do stuff
        }

        private void Process_Exited(object? sender, EventArgs e)
        {
            MessageBox.Show("Done");
        }

PS: I'm aware that there are several posts about this issue, and I've checked them, but none of them helped, so here I am.

CodePudding user response:

  • At risk of sounding hostile, you should not be subclassing .NET's own Process class.
    • After looking at your code I get the feeling that you're new to the whole "composition vs. inheritance" thing, so, you need to know that the long-and-short of it (enter image description here
    • Double-click FormClosed to add the event handler to Form1

    Form1:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    namespace ProcessTest
    {
        public partial class Form1 : Form
        {
            private HelperProcess _process = null;
            public Form1()
            {
                InitializeComponent();
    
                string fPath = string.Empty;
    
                //environment variable windir has the same value as SystemRoot
                //use 'Sysnative' to access 64-bit files (in System32) if program is running as 32-bit process
                //use 'SysWow64' to access 32-bit files on 64-bit OS
    
                if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
                    fPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "Sysnative", "wbem", "wmic.exe");
                else
                    fPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "wbem", "wmic.exe");
    
                //create new instance
                _process = new HelperProcess(fPath);
    
                //subscribe to events
                _process.DataReceived  = Process_DataReceived;
                _process.ProcessExited  = Process_ProcessExited;
            }
    
            private async void btnRun_Click(object sender, EventArgs e)
            {
                Debug.WriteLine("before Execute");
                await Execute();
                Debug.WriteLine("after Execute");
            }
    
            private async Task Execute()
            {
                await _process.Run("process get");
    
                Debug.WriteLine("after _process.Run");
            }
    
            private void Process_ProcessExited(object sender, EventArgs e)
            {
                Debug.WriteLine("Main: Process_ProcessExited");
            }
    
            private void Process_DataReceived(object sender, DataReceivedEventArgs e)
            {
                Debug.WriteLine($"Main: Process_DataReceived: {e.Data}");
            }
    
            private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
                if (_process != null)
                {
                    //unsubscribe from events
                    _process.DataReceived -= Process_DataReceived;
                    _process.ProcessExited -= Process_ProcessExited;
                }
            }
        }
    }
    

    Resources:

  • Related