/// <summary> /// Raises the <see cref="Progress"/> event. /// </summary> /// <param name="e"> /// The event arguments. /// </param> protected void OnProgress(PingProgressEventArgs e) { if (this.Progress != null) { this.Progress(this, e); } }
/// <summary> /// Monitors the process and reads it's output. This method should only /// execute in the reader thread. /// </summary> protected override void ProcessReader() { ProcessOutputEventArgs outArgs = null; PingProgressEventArgs progress = null; var output = String.Empty; var errMsg = String.Empty; var i = 1; var count = this._count; var succeeded = 0; var failed = 0; Match mReply = null; Match mFailed = null; try { // Start the process and raise the running event. this._pingProc.Start(); base.OnProcessStarted(new ProcessStartedEventArgs(this._pingProc.Id)); // Read the output until the process terminates. output = this._pingProc.StandardOutput.ReadLine(); while ((output != null) && (!base.WasCancelled)) { // Notify output listeners. outArgs = new ProcessOutputEventArgs(output); base.OnOutputReceived(outArgs); // See if the output message is a ping reply. mReply = this._reReply.Match(output); mFailed = this._reFailed.Match(output); if ((mReply.Success) || (mFailed.Success)) { // If we're pinging continuously, the request count and // current request are always equal. if (this._continuous) { count = i; } // Compute responses received and lost. if (mReply.Success) { succeeded++; } if ((mFailed.Success) || (output.Contains("unreachable"))) { failed++; } // Raise progress event. progress = new PingProgressEventArgs(i, succeeded, failed, count); this.OnProgress(progress); i++; } // This loop is blocking, which is why we are using a thread. output = this._pingProc.StandardOutput.ReadLine(); } // Wait for the process to finish up, then get the exit code. this._pingProc.WaitForExit(); base._exitCode = this._pingProc.ExitCode; // If the progress hits 100% or the process terminated normally, // the notify listeners that we're done. Otherwise, notify output // and cancellation listeners. if ((base._exitCode == 0) || ((progress != null) && (progress.PercentComplete == 100))) { base.OnProcessFinished(new ProccessDoneEventArgs(base._exitCode)); } else { errMsg = "A ping error occured: " + PingUtils.GetPingErrorMessage(this.ExitStatus) + " Error code: " + base._exitCode.ToString(); base.OnOutputReceived(new ProcessOutputEventArgs(errMsg)); base.OnProcessCancelled(ProcessCancelledEventArgs.Empty); lock (_flagLock) { base._wasCancelled = true; } } } catch (InvalidOperationException) { // This will occur if the Cancel() or Dispose() methods are called, // since this is expected to occur under these conditions, then just // raise the ProcessCancelled event. base.OnProcessCancelled(ProcessCancelledEventArgs.Empty); lock (_flagLock) { base._wasCancelled = true; } } catch (Exception ex) { errMsg = "An error occurred while reading process output: " + ex.ToString(); outArgs = new ProcessOutputEventArgs(errMsg); base.OnOutputReceived(outArgs); base.OnProcessCancelled(new ProcessCancelledEventArgs(ex)); lock (_flagLock) { base._wasCancelled = true; } } finally { // Destroy the process and update the state flag. if (this._pingProc != null) { this._pingProc.Close(); this._pingProc.Dispose(); } lock (_flagLock) { base._isRunning = false; } } }