3

I am trying to kill the process by process ID which I am saving when the process start. But the process ID which I am capturing doesn't exists when I try to kill the process from code behind.

This is the code below to start the process and capture the process ID.

private List<int> pids = new List<int>();
public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            pids.Clear();
            Process myprocess= new Process();

            myprocess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\system32\cmdkey.exe");
            myprocess.StartInfo.Arguments = "C:\\rdp\\RemoteIn.rdp";
            myprocess.Start();
            pids.Add(myprocess.Id);          
        }

        private void terminateAll()
        {
            //foreach (var p in pids) p.Kill();

            foreach (var i in pids)
            {
                Process p = Process.GetProcessById(i);
                p.Kill();

            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            terminateAll();
        }

When I click button to terminate the process it shows following error.

enter image description here

Is there any way to fix this.

After using Palani Kumar code, I am getting below exception. enter image description here

Form Looks like this

enter image description here

Amrit Sharma
  • 1,906
  • 8
  • 45
  • 75

2 Answers2

1

I don't know why you are declared pids as List<int> and cleared the list (pids.Clear();) on button click event. Anyway the below will work for creating multiple processes also.

EDIT: As so far discussed with Amrit. The Windows 8 creating sub processes for mstsc with connecting same domain. So I slightly modified my code.

    private void button1_Click(object sender, EventArgs e)
    {
        //pids.Clear();
        Process myprocess = new Process();

        myprocess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(@"%SystemRoot%\syswow64\mstsc.exe");
        myprocess.StartInfo.Arguments = "C:\\rdp\\RemoteIn.rdp";
        myprocess.Start();
        Thread.Sleep(100);
        /* Edit */
        Process proc = Process.GetProcessesByName("mstsc").FirstOrDefault(x => !pids.Any(y => y == x.Id));
        if(proc != null)
        {
           pids.Add(proc.Id);
        }
    }

And

    private void terminateAll()
    {
        foreach (var i in pids)
        {
            try
            {
                Process p = Process.GetProcessById(i);
                p.Kill();
            }
            catch (Exception ex)
            {
                //throw exception if we close the mstsc manually
            }
        }
    }
Palanikumar
  • 6,940
  • 4
  • 40
  • 51
0

I'm not sure why you hold

private List<int> pids = new List<int>();

instead of usage just the list of Process directly

private List<Process> processes = new List<Process>();

It's important to understand that the Process object have security descriptor. Everybody can see the existence of the process, someone can open the process for reading information or for waiting for the the end of process. Opening for killing require more rights. The process handle returned by CreateProcess have full permissions. So holding of Process object used for creating the process gives you such advantages.

I would recommend you additionally to test HasExited property of Process object before calling of Kill() method. One can consider to use OnExited additionally (see here) to remove the process if it will be closed by the user. You should call Close() method of Process object in any way before removing from the processes list and consider to use CloseMainWindow() instead of Kill() method. You should just test both methods (CloseMainWindow() and Kill()) and to choose the best for your case.

Oleg
  • 220,925
  • 34
  • 403
  • 798