由进程启动的进程的进程ID

3
我正在尝试通过保存进程启动时生成的进程 ID 来终止该进程。但是,当我尝试从代码中终止该进程时,我捕获的进程 ID 并不存在。
以下是用于启动进程和捕获进程 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();
        }

当我点击终止进程按钮时,它显示以下错误。 enter image description here 有没有办法修复这个问题?
使用 Palani Kumar 代码后,我遇到了以下异常。 enter image description here 表格看起来像这样 enter image description here

1
尝试将 Process 对象保存在您的列表中,而不仅仅是它的 Id。 - Blorgbeard
是的,与其储存进程 ID,不如直接储存进程本身,这样你甚至都不需要调用 Process.GetProcessById(i) - spender
1
可能是通过Process.start()获取启动进程的PID的重复问题。 - Hari Prasad
2
顺便提一下:异常很可能会告诉你真相——你正在通过CMD启动其他进程,因此CMD在此之后可以自由存在。 - Alexei Levenkov
使用进程名称而非进程 ID 处理,请使用以下代码:Process p=Process.GetProcessesByName("YourProcessName"); - Jagadeesh Govindaraj
显示剩余2条评论
2个回答

1
我不知道为什么你将pids声明为List<int>并在按钮点击事件中清除了列表(pids.Clear();)。无论如何,以下内容也适用于创建多个进程。
编辑:根据与Amrit的讨论,Windows 8为mstsc创建子进程并连接相同的域。因此,我稍微修改了我的代码。
    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);
        }
    }

    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
            }
        }
    }

如果我只打开一个 .rdp 文件,它就像魔法一样运行良好。但是当我打开另一个 .rdp 文件时,它会抛出上述错误。 - Amrit Sharma
你有注释这行代码吗:“pids.Clear();”? - Palanikumar
是的,我已经注释掉了 pids.Clear()。 - Amrit Sharma
我需要打开多个 .rdp 文件。 - Amrit Sharma
嗯...我用多个测试了这个,一切正常。然后尝试增加Thread.Sleep的值,并检查进程ID是否与任务管理器中创建的PID匹配。 - Palanikumar
显示剩余3条评论

0

我不确定你为什么持有

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

不要直接使用Process列表,而是使用它。

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

理解进程对象具有安全描述符是很重要的。每个人都可以看到进程的存在,有些人可以打开进程以读取信息或等待进程结束。杀死进程需要更多的权限。由CreateProcess返回的进程句柄具有完全权限。因此,持有用于创建进程的Process对象会给您带来这样的优势。

在调用Kill()方法之前,我建议您另外测试Process对象的HasExited属性。可以考虑使用OnExited(请参见此处)在用户关闭进程时删除进程。在从processes列表中删除之前,无论如何都应该调用Process对象的Close()方法,并考虑使用CloseMainWindow()而不是Kill()方法。您应该测试两种方法(CloseMainWindow()Kill()),并选择最适合您情况的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接