使用命令行获取进程 ID

Posted

技术标签:

【中文标题】使用命令行获取进程 ID【英文标题】:Getting ProcessId with CommandLine 【发布时间】:2018-09-12 14:07:19 【问题描述】:

我已经在这里搜索了答案,但找不到任何有效的代码 sn-ps 或提示。

如何使用给定的命令行获取 ProcessId?我已经用这个方法通过 Pid 获得了 CommandLine:

private IEnumerable<string> GetCommandLine(Process process)

    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id))
    using (ManagementObjectCollection objects = searcher.Get())
    
        foreach (var element in objects)
            yield return element["CommandLine"]?.ToString();
    

这适用于获取具有给定 ProcessId 的命令行。 但我想要带有给定命令行的 ProcessId。 我开始了一个进程,其中包含我正在搜索的这个命令行。 这是我的尝试:

private IEnumerable<int> GetIdsByCommandLine(string commandLine)

    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ProcessID FROM Win32_Process WHERE CommandLine = " + commandLine))
    using (ManagementObjectCollection objects = searcher.Get())
    
        foreach (var element in objects)                
            yield return (int) element["ProcessId"];                
    

但如果我运行它,它会在 foreach 循环的开始处停止:“查询无效” 任何人都可以通过这样的查询帮助我通过命令行获取 ProcessId 吗? 提前致谢!

编辑: 我需要这个作为进程看门狗。我有 4 个以参数开头的程序。但是在它们开始之前不应该有这些程序的任何实例。所以我的尝试是启动每个,获取进程的CommandLine(上面的GetCommandLine),杀死进程,然后我想搜索具有相同CommandLine的进程来杀死它们。只有完成此操作后,我才能启动我的 4 个程序,而不会让它们四处乱窜。这就是为什么我需要一种通过命令行提取 processIds 的方法。

【问题讨论】:

试试看a similar *** question。 是否像在第二个示例中需要引用字符串一样简单?首先,您不需要在 pid 周围加上引号,因为它是数字的。在命令行的情况下,虽然它是一个字符串,所以可能需要被引用。我从来没有使用过这项技术,所以不确定,但鉴于它是类似 SQL 的语法,我认为这是一个合理的猜测...... @Chris 这听起来很合理,你知道这会是什么样子吗? @csharpforevermore 与 Name 和 ProcessId 没有问题。这些查询也对我有用。但是我需要命令行的过程,在我的帖子上查看我的编辑,这解释了原因。不过谢谢你的回答。 @JayBeAl:好吧,如果所有其他方法都失败了,您可能只是删除 WHERE,然后使用 LINQ 在内存中检查您想要的东西。也会使调试更容易。 :) 【参考方案1】:

也尝试使用范围参数。

private IEnumerable<int> GetIdsByCommandLine(string commandLine)

    string queryString = "SELECT ProcessID FROM Win32_Process WHERE CommandLine = " + commandLine;
    string wmiScope = @"\\your_computer_name\root\cimv2";
    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiScope, queryString))
    using (ManagementObjectCollection objects = searcher.Get())
        foreach (ManagementBaseObject element in objects)
            yield return (int)element["ProcessId"];

请记住,命令行会根据进程的调用方式而有所不同,因此这不是 100% 可靠的。我假设您将一次传递一个字符串列表,从GetCommandLine()GetIdsByCommandLine()

这是没有意义的,因为您只需将上面的 queryString 参数更改为

string queryString = "SELECT Name, CommandLine, ProcessId, Caption, ExecutablePath FROM Win32_Process";

根据this *** answer。这将允许您一次获取进程 ID 和命令行,而无需枚举响应并多次调用数据库。

【讨论】:

这和@Chris 在我的帖子中的第三条评论帮助了我。我现在只需使用 ProcessId 和 CommandLine 获取对象,然后使用 Linq 来获取我想要的。谢谢! 很高兴它有帮助。感谢您选择我的答案。祝你好运!【参考方案2】:

也许这对你有用。

using System.Diagnostics;
public class KillProcess

    [DllImport("user32.dll")]
    static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);


    Process _KillProcess(int Hwnd)
    
        int id;
        GetWindowThreadProcessId(Hwnd, out id);

        Process _Process = Process.GetProcessById(id);

        _Process.Kill();
    

另外,另一种方式是

System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");

foreach (System.Diagnostics.Process p in process)

    if (!string.IsNullOrEmpty(p.ProcessName))
    
        try
        
            p.Kill();
        
        catch  
    

【讨论】:

这看起来不像是回答了这个问题。 OP 想要查找给定命令行的进程,而不是名称。 是的@Rup 是对的,我无法使用这些名称,我需要命令行中的 processId。不过谢谢

以上是关于使用命令行获取进程 ID的主要内容,如果未能解决你的问题,请参考以下文章

从 32 位进程获取 64 位进程的命令行字符串

如何获取启动进程的命令行

如何在 PowerShell 或 C# 中获取进程的命令行信息

Gcloud命令行获取默认project_id

执行 psql/mysql CLI 命令行后如何获取查询 ID?

Windows中使用命令行杀进程