如何识别正在运行的进程

Posted

技术标签:

【中文标题】如何识别正在运行的进程【英文标题】:How to identify running process 【发布时间】:2021-11-28 08:17:34 【问题描述】:

一般问题:如何从运行在同一台服务器上的网络应用中识别进程?假设我们从不同的控制台应用程序启动此过程,但我们可以将有关此过程的任何数据保存到数据库中,该数据库可供 Web 应用程序访问。

我的具体设置,以及更详细的问题描述:

设置: 我有一个控制台应用程序——我们称之为包装器。这个应用程序正在启动一个 CPU 繁重的进程,我们称之为计算器进程。 Wrapper 还将有关此过程的信息保存到数据库 - 一条记录。我还有一个 Web 应用程序 - 仪表板 - 显示有关服务器上所有正在运行的控制台应用程序和计算器进程的信息(从数据库中获取的信息)。 Calculator Process 完成后,Wrapper 将完成时间保存到数据库,我可以在 Dashboard 中显示它已经完成。

问题: 有时 Wrapper 会死掉,而 Calculator Process 也会随之消亡。当它死亡时,它不会将任何信息保存到数据库中,所以我留下了一条未完成状态的记录。

问题: 在 Dashbord 中,如何识别哪些未完成的记录是正在运行的计算,哪些是 Wrapper 死后的剩余记录?

澄清:每个 Wrapper 都由某个外部代理启动/结束。每个 Wrapper 启动一个单独的 Calculator Process。 Wrapper 正在等待进程完成,然后更新数据库记录,然后退出。 Wrapper突然死掉了,那么记录没有更新,问题就出现了。

我尝试过的解决方案: 我尝试将计算器进程的 StartTime 保存到数据库中。然后在仪表板中,我尝试按名称检查所有正在运行的计算器进程,从 System.Diagnostics.Process 类中获取它们的 StartTime。我的想法是查看哪些未完成的进程与正在运行的进程具有相同的 StartTime。那就是我将能够区分正在运行的和死掉的。但我得到:

Win32Exception: Access is denied
    System.Diagnostics.ProcessManager.OpenProcess(int processId, int access, bool throwIfExited)
    System.Diagnostics.Process.GetProcessHandle(int access, bool throwIfExited)
    System.Diagnostics.Process.GetProcessTimes()
    System.Diagnostics.Process.get_StartTime()

【问题讨论】:

你能澄清When Wrapper suddenly dies的意思吗?它是怎么死的? @the.Doc - 我认为,启动 Wrapper 的同一个外部代理有时会在它完成之前杀死它。它不在我的控制范围内。 您可以尝试Win32_ProcessStartTraceWin32_ProcessEndTrace 来监控您的进程何时启动/存在。您可能需要一个后台线程/进程,但不确定 wmi 事件如何与 asp.net 一起使用。除非您有权访问服务器以安装为服务? 【参考方案1】:

好的,所以最后我通过使用不同的方式访问流程数据来修复它。

using System.Management;

我使用 System.Management 从计算器进程中读取 CreationDate。

public IEnumerable<string> GetTimestampIdOfRunningProcesses(string processName)

    var managementClass = new ManagementClass("Win32_Process");
    foreach (var process in managementClass.GetInstances())
    
        var name = process["Name"].ToString();
        if (name.StartsWith(processName))
        
            var startTimeText = process["CreationDate"].ToString();
            var startTime = ManagementDateTimeConverter.ToDateTime(startTimeText);
            yield return startTime.ToTimestampId();
        
    

其他详情:

当我开始这个过程时,我得到它的 StartTime。

public DateTime StartProcess(string path)

    using (var process = new SystemProcess())
    
        process.StartInfo = CreateProcessStartInfo(path);
        process.Start();
        return process.StartTime;
    

然后我将其转换为统一格式的字符串(使用扩展方法)。

public static string ToTimestampId(this DateTime dateTime)

    return dateTime.ToString("yyyy.MM.dd HH:mm:ss.ffffff");

这是我统一 System.Management 读取的数据(精度有限)和我在流程开始时获得的非常精确的 StartTime 的方法。这样我可以比较两个值。

【讨论】:

以上是关于如何识别正在运行的进程的主要内容,如果未能解决你的问题,请参考以下文章

通过“密钥”识别进程

如何检查正在运行的进程是不是是后台进程? [关闭]

如何在Linux中查看所有正在运行的进程

如何查看linux 正在运行的进程

如何使用 C++ 检查进程是不是正在运行

如何在Linux中查看所有正在运行的进程