0

I've created a button that starts a "CMD" process and pings a specific machine.

I've got it to Ping successfully, and change the button text back and forth after clicking the button, but I'm not sure how to STOP the ping process (which is a ping -t command) on the second click of the same button.

HERE is my code so far, which selects the button, changes the text on click, starts the process and checks for errors. I've tried to add an "else" statement and say proc.Kill(), but it cant find the proc variable everywhere I try. Is there a correct way to do this?

    public void Btn_Ping_Click_1(object sender, EventArgs e)
    {

        if (Btn_Ping.Text == "Ping")
        {
            Btn_Ping.Text = "Stop Ping";
        }
        else if (Btn_Ping.Text == "Stop Ping")
        {
            Btn_Ping.Text = "Ping";
        }
        th = new Thread(thread1);
        th.Start();
    }

    public void thread1()
    {
        if (Btn_Ping.Text == "Stop Ping")
        {
            try
            {
                string command = "/c ping " + Txt_Main.Text.Trim() + " -t";
                ProcessStartInfo procStartInfo = new ProcessStartInfo("CMD", command);
                Process proc = new Process();
                proc.StartInfo = procStartInfo;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardInput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.CreateNoWindow = true;
                proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutPutDataRecieved);
                proc.Start();
                proc.BeginOutputReadLine();
                proc.WaitForExit();

            }
            catch (Exception)
            {
                //If an error occurs within the try block, it will be handled here
            }
        }

        void proc_OutPutDataRecieved(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                string newLine = e.Data.Trim() + Environment.NewLine;
                MethodInvoker append = () => richTextBox1.Text += newLine;
                richTextBox1.BeginInvoke(append);
            }
        }
    }
William
  • 23
  • 4
  • Can't you just declare the Process in the class and call Kill in the other method? – Simon Apr 05 '19 at 14:17
  • Echoing what I said below, I can't believe I didn't think to do that. Thank you. New developer here and I frequently miss small things like that :( – William Apr 05 '19 at 15:55
  • https://stackoverflow.com/questions/30249873/process-kill-doesnt-seem-to-kill-the-process This seems to imply that running CMD to ping doesn't respond to proc.Kill() try running it directly instead. – Thomas N Apr 08 '19 at 06:41

2 Answers2

0

Declare proc at the class level (instead of inside thread1). Then add to the button Click event:

if(proc != null)
{
    if (!proc.HasExited)
        proc.Kill();
    proc = null;
}
else
{
    th = new Thread(thread1);
    th.Start();   
}
Thomas N
  • 623
  • 1
  • 4
  • 14
  • Wow, I can't believe I didn't think to just declare proc in the class. Ugh, thank you. – William Apr 05 '19 at 15:55
  • I tried to say Process proc = new Process(); above in the class, as well as just saying Process proc; and initiating it below, but neither are working. The initial ping just keeps on going. – William Apr 05 '19 at 16:34
0

Use Task objects rather than threads. Pass CancelationToken objects in to them like this:

      private CancellationTokenSource _cts = null;

      public void Btn_Ping_Click_1(object sender, EventArgs e)
      {
         if (Btn_Ping.Text == "Ping")
         {
            _cts = new CancellationTokenSource();
            Btn_Ping.Text = "Stop Ping";
            var task = new Task(() => task1(cts.Token));
            task.Start();
         }
         else if (Btn_Ping.Text == "Stop Ping")
         {
            Btn_Ping.Text = "Ping";
            _cts.Cancel();
         }
      }

      public void task1(CancellationToken ct)
      {
         try
         {
            string command = "/c ping " + Txt_Main.Text.Trim() + " -t";
            var procStartInfo = new ProcessStartInfo("CMD", command);
            var proc = new Process {StartInfo = procStartInfo};
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutPutDataRecieved);
            proc.Start();
            proc.BeginOutputReadLine();
            while (!proc.WaitForExit(250))
            {
               if (ct.IsCancellationRequested)
               {
                  proc.Kill();
                  return;
               }
            }
         }
         catch (Exception)
         {
            //If an error occurs within the try block, it will be handled here
         }
      }
Steve Todd
  • 1,250
  • 6
  • 13