【问题标题】:Getting ProcessId with CommandLine使用命令行获取进程 ID
【发布时间】: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 的方法。

【问题讨论】:

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

标签: c# wmi


【解决方案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 StackOverflow 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。不过谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 1970-01-01
  • 2020-01-20
  • 1970-01-01
  • 2012-10-28
  • 2011-05-14
  • 1970-01-01
相关资源
最近更新 更多