none
why Process Exited event not fired when expected? RRS feed

  • Question

  • I am using System.Diagnostics.Process to launch a process that runs CMD.EXE.  I hook the Exited event of the process. After I launch the CMD.EXE process I send it the "exit" command thru StandardInput. The cmd.exe window shutsdown. But the Exited event does not fire. The event does not fire until the HasExited property of the process object is read.  Why does the exit event not fire when the cmd.exe window shutsdown?

    Here is a WPF application that illustrates the problem. Click Launch to start the cmd.exe process. Click Exit to send the exit command and see the cmd.exe window shutdown. Click the Query has exited button to see that the exited event does not fire until the HasExited property is read. The code uses Trace.WriteLine to record what is happending. View the messages in the Output window of visual studio.

    thanks,

    <Window x:Class="CmdShell.Windows.ExitedEventProblem"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="ExitedEventProblem" Height="300" Width="300">
        <Grid>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
          <Button x:Name="Launch" Margin="5" Click="Launch_Click">Launch</Button>
          <Button x:Name="Exit" Margin="5" Click="Exit_Click">Exit</Button>
          <Button x:Name="QueryHasExited" Click="QueryHasExited_Click">Query has exited</Button>
        </StackPanel>
      </Grid>
    </Window>
    
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.Diagnostics;
    using System.Threading;
    
    namespace CmdShell.Windows
    {
      /// <summary>
      /// Interaction logic for ExitedEventProblem.xaml
      /// </summary>
      public partial class ExitedEventProblem : Window
      {
        public Process CmdProcess;
    
        public ExitedEventProblem()
        {
          InitializeComponent();
        }
    
        private void Launch_Click(object sender, RoutedEventArgs e)
        {
          LaunchCmdProcess();
        }
    
        private void Exit_Click(object sender, RoutedEventArgs e)
        {
          this.CmdProcess.StandardInput.WriteLine("exit");
          this.CmdProcess.StandardInput.Flush();
          Trace.WriteLine("exit command run");
        }
    
        private void QueryHasExited_Click(object sender, RoutedEventArgs e)
        {
          Trace.WriteLine("HasExited:" + this.CmdProcess.HasExited);
          if (this.CmdProcess.HasExited == true)
          {
            Trace.WriteLine("ExitCode:" + this.CmdProcess.ExitCode);
          }
        }
    
        void LaunchCmdProcess()
        {
          this.CmdProcess = new Process();
          var ps = new ProcessStartInfo();
          ps.FileName = "cmd.exe";
          ps.UseShellExecute = false;
          ps.WindowStyle = ProcessWindowStyle.Normal;
          ps.CreateNoWindow = false;
          ps.RedirectStandardInput = true;
          ps.RedirectStandardOutput = true;
          ps.RedirectStandardError = true;
          this.CmdProcess.StartInfo = ps;
    
          this.CmdProcess.Exited += new EventHandler(CmdProcess_Exited);
    
          this.CmdProcess.Start();
    
          ReadStandardOutputThread();
          ReadStandardErrorThread();
        }
    
        void CmdProcess_Exited(object sender, EventArgs e)
        {
          Trace.WriteLine("Process has exited event has fired.");
        }
    
        void ReadStandardErrorThread()
        {
          ThreadPool.QueueUserWorkItem(
            (o) =>
            {
              int bufferSize = 10240;
              char[] buffer = new char[bufferSize];
              while (true)
              {
                int count = this.CmdProcess.StandardOutput.Read(buffer, 0, bufferSize);
                if (count > 0)
                {
                  var s1 = new String(buffer, 0, count);
                  Trace.WriteLine(s1);
                }
              }
            });
        }
    
        void ReadStandardOutputThread( )
        {
          ThreadPool.QueueUserWorkItem(
            (o) =>
            {
              int bufferSize = 10240;
              char[] buffer = new char[bufferSize];
              while (true)
              {
                int count = this.CmdProcess.StandardOutput.Read(buffer, 0, bufferSize);
                if (count > 0)
                {
                  var s1 = new String(buffer, 0, count);
                  Trace.WriteLine(s1) ;
                }
              }
            });
        }
      }
    }
    
    

    Tuesday, March 6, 2012 12:13 AM

Answers

All replies